4.1什麼是樹&二叉樹
該樹的每個結點至多隻有兩顆子樹
特殊的二叉樹
1.滿二叉樹
2.完全二叉樹
注:判斷二叉樹是否爲完全二叉樹https://blog.csdn.net/lin1094201572/article/details/86083106
4.2二叉樹的存儲
1.順序存儲結構
2.鏈式存儲機構
4.3.1二叉樹的遍歷
根節點的訪問順序是先還是中還是後決定先,中,後序訪問
1.先序遍歷(PreOrder):
void preOrder(BinaryTree T){
if(T!=NULL){
visit(T);
preOrder(T->lchild);
preOrder(T->rchild);
}
}
2.中序遍歷(InOrder)
遞歸算法:
void inOrder(BinaryTree T){
if(T!=NULL){
inOrder(T->lchild);
visit(T);
inOrder(T->rchild);
}
}
非遞歸算法:
1.利用棧
void inOrder_no_recursion(BinaryTree T){
initStack(S);BinaryTree p=T;
while(p||!isEmpty(S)){
if(p){
Put(S,p);
p=p->lchild;
}else{
Pop(S,p);
p=p->rchild;
}
}
}
3.後序遍歷(PostOrder)
void postOrder(BinaryTree T){
if(T!=NULL){
postOrder(T->lchild);
postOrder(T-rchild);
visit(T);
}
}
已知(先或後)+中序可唯一確定一棵二叉樹。
時間複雜度分析和空間複雜度
1.三種遍歷都訪問每個結點故遍歷時間複雜度爲O(n)
2.遞歸所需最多的棧個數由二叉樹的深度h決定,最壞情況爲全爲度爲1的單支結點深度爲n則空間複雜度爲O(n).
4.層次遍歷(LevelOrder)
1.利用隊列
1)隊列中首先加入根結點, 隊中A
2)隊列出隊得得隊首元素,訪問出隊元素
3)將出隊元素的左右子結點加入隊列,
循環2)3)
隊中:A–null–BC–CEF–EF–F--null
void levelOrder(BinaryTree T){
initQueue(Q);
BinaryTree p=T;EnQueue(S,p);
while(p){
DeQueue(S,p);visit(p);
if(p->lchild!=NULL) EnQueue(S,p->lchild);
if(p->rchild!=NULL) EnQueue(S,p->rchild);
}
}
4.3.2 線索二叉樹
將鏈式存儲的二叉樹的空指針利用,一個結點添加兩個個標籤域。分別爲ltag,rtag.
將空白指針指向前驅或後繼,左空指向前驅,有空指向後繼,稱爲線索。
前驅,後繼由當前線索數的順序(先,中,後序)決定。
將二叉樹以某種次序線索化後得到線索二叉樹
ltag爲0指向左兒子結點,爲1指向該前驅。
rtag爲0指向右兒子結點,爲1指向該後繼。
該線索二叉樹結構體如下:
typedef struct struct_ThreadNode{
ElemType elem;
struct struct_ThreadNode *lchild,*rchild;
int ltag,rtag;
}ThreadNode ,*ThreadTree;
Demo of the algorithm of InOrder-ThreadTree :
void in_Thread(ThreadTree &p,ThreadTree &pre){//p,pre需修改結點故引用,引用爲c++中添加特性
if(p!=NULL){
//遞歸線索化左子樹
//將當前結點的左右若空線索化,左空前驅(中序前驅爲pre),右空後繼(中序,後繼爲根結點p)。
pre = p;//線索化後前驅結點變換爲當前根結點。
//遞歸線索化右子樹
}
}
The code of sort InOrder-ThreadTree by InOrder:
void inorder_ThreadTree(ThreadTree T){
for(ThradNode *p=FirstNode(T);p!=NULL;p=NextNode(T)) visit(p);
}