**樹**
樹的知識真的是很多!!!!
(一開始我以爲排序內容多呢,跪倒在樹面前,)
等九月份再二刷吧!!!!!
下圖整體結構框架
感覺比排序多的不是一點點!!!!!
王道中的算法
1.二叉樹的鏈式存儲結構
//二叉樹的鏈式存儲結構
typedef struct BiTNode{
ElemType data;//數據域
struct BiTNode *lchild,*rchild;//左,右孩子指針
};
2.遍歷
//先序遍歷(記憶)
void PreOrder(BiTree T)
{
if(T!=NULL)
{
visit(T);//訪問根結點
PreOrder(T->lchild);//訪問遍歷左子樹
PreOrder(T->rchild);//訪問遍歷右孩子
}
}
//中序遍歷(記憶)
void InOrder(BiTree T)
{
if(T!=NULL)
{
PreOrder(T->lchild);//訪問遍歷左子樹
visit(T);//訪問根結點
PreOrder(T->rchild);//訪問遍歷右孩子
}
}
//後序遍歷(記憶)
void PostOrder(BiTree T)
{
if(T!=NULL)
{
PreOrder(T->lchild);//訪問遍歷左子樹
PreOrder(T->rchild);//訪問遍歷右孩子
visit(T);//訪問根結點
}
}
//中序遍歷的非遞歸算法
void InOrder2(BiTree T)
{
//二叉樹中序遍歷的非遞歸算法,算法需要藉助一個棧
InitStack(S);BiTree p=T;//初始化棧;p是遍歷指針
while(p||!IsEmpty(S)){ //棧不空或p不空時循環
if(p){ //根指針進棧,遍歷左子樹
Push(S,p);//每遇到非空二叉樹先向左走
p=p->lchild;
}
else{ //根指針退棧,訪問根結點,遍歷右子樹
Pop(S,p);visit(p);
p=p->rchild;
}
}
}
//層次遍歷(記憶)
void LevelOrder(BiTree T)
{
InitQueue(Q);//初始化輔助隊列
BiTree p;
EnQueue(Q,T);//將根結點入隊
while(!IsEmpty(Q)){//隊列不空循環
DeQueue(Q,p);//隊頭元素出隊
visit(p);//訪問當前p所指向結點
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);//左子樹不空,則左子樹入隊列
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);//右子樹不空,則右子樹入隊列
}
}
3.線索二叉樹
//線索二叉樹
//線索二叉樹的存儲結構
typedef struct ThreadNode{
ElemType data;//數據元素
struct ThreadNode *lchild,*rchild;//左,右孩子指針
int ltag,rtag;//左右線索標誌
}ThreadNode,*ThreadTree;
//中序遍歷對二叉樹線索化的遞歸算法
//指針pre指向中序遍歷時上一個剛剛訪問過的結點,用它來表示各結點訪問的前後關係
void InThread(Thread &p,ThreadTree &pre)
{
if(p!=NULL){
InThread(p->lchild,pre);//遞歸,線索化左子樹
if(p->lchild==NULL){
//左子樹爲空,建立前驅線索
p->lchild=pre;
p->ltag=1;
}
if(pre!=NULL &&pre->rchild==NULL){
pre->rchild=p;//建立前驅結點的後繼線索
pre->rtag=1;
}
pre=p;//標記當前結點成爲剛剛訪問過的結點
InThread(p->rchild,pre);//遞歸,線索化右子樹
}
}
//中序遍歷建立中序線索二叉樹的主過程算法
void CreateInThread(ThreadTree T)
{
ThreadTree pre=NULL;
if(T!=NULL){
//非空二叉樹,線索化
InThread(T,pre);//線索化二叉樹
pre->rchild=NULL;//處理遍歷的最後一個結點
pre->rtag=1;
}
}
//線索二叉樹的遍歷
//求中序線索二叉樹中中序序列下的第一個結點
ThreadNode *Firstnode(ThreadNode *p)
{
while(p->ltag==0) p=p->lchild;//最左下結點(不一定是葉結點)
return p;
}
//求中序線索二叉樹中結點p在中序序列下的後繼結點
ThreadNode *Nextnode(ThreadNode *p)
{
if(p->rtag==0) return Firstnode(p->rchild);
else return p->rchild;//rtag==1直接返回後繼線索
}
//不含頭結點的中序線索二叉樹的中序遍歷算法
void Inorder(ThreadNode *T)
{
for(ThreadNode *p=Firstnode(T);p!=NULL;p=Nextnode(p))
visit(p);
}
4.並查集
//並查集的結構定義
#define SIZE 100
int UFSets(SIZE);//集合元素數組(雙親指針數組)
//並查集的初始化操作(S即爲並查集)
void Initial(int S[])
{
for(int i=0;i<size;i++)//每個自成單元素集合
S[i]=-1;
}
//Find操作(函數在並查集S中查找並返回包含元素x的樹的根)
int Find(int S[],int x)
{
while(S[x]>=0)//循環尋找x的根
x=S[x];
return x;//根的S[]小於0
}
//Union操作(函數求兩個不相交子集合的並集)
void Union(int S[],int Root1,int Root2)
{
//要求Root1與Root2是不相同的,且表示子集合的名字
S[Root2]=Root1;//將根Root2連接到另一根Root1下面
}
5.二叉排序樹
//二叉排序樹
//二叉排序樹的查找
BSTNode *BST_Search(BiTree T,ElemType key,BSTNode *&p)
{
//查找函數返回關鍵字值爲key的結點指針,若不存在,返回NULL
p=NULL;//p指向被查找結點的雙親,用於插入和刪除操作中
while(T!=NULL && key!=T->data){
p=T;
if(key<T->data) T=T->lchild;
else T=T->rchild;
}
return T;
}
//二叉排序樹的插入
int BST_Insert(BiTree &T,KeyType k)
{
//在二叉排序樹T中插入一個關鍵字爲k的結點
if(T==NULL)
{
//原樹爲空,新插入的記錄爲根結點
T=(BiTree)malloc(sizeof(BSTNode));
T->key=k;
T->lchild=T->rchild=NULL;
return 1;//返回1,表示成功
}
else if(k==T->key)//樹中存在相同關鍵字的結點
return 0;
else if(k<T->key)
return BST_Insert(T->lchild);//插入T的左子樹
else
return BST_Insert(T->rchild);//插入T的右子樹
}
//二叉排序樹的構造
void Creat_BST(BiTree &T,KeyType str[],int n)
{
//用關鍵字數組str[]建立一個二叉排序樹
T=NULL;//初始時bt爲空樹
int i=0;
while(i<n){
//依次將每個元素插入
BST_InSert(T,str[i]);
i++;
}
}