typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; // struct node *parent; // 指向雙親的指針 (無關緊要) } bintnode; typedef bintnode *bintree; bintree root; // 指向二叉樹根結點的指針
前序遍歷:首先訪問根結點;
而後按照前序遍歷的順序訪問根結點的左子樹;
再按照前序遍歷的順序訪問根結點的右子樹node
中序遍歷:首先按照中序遍歷的順序訪問根結點的左子樹;
而後訪問根結點;最後按照中序遍歷的順序訪問根結點的右子樹算法
後序遍歷:首先按照後序遍歷的順序訪問根結點的左子樹;
而後按照後序遍歷的順序訪問根結點的右子樹;最後訪問根結點函數
圖二叉樹的遍歷:spa
二叉樹遍歷的遞歸實現 :按照遍歷規定的次序,訪問根結點時就輸出根結點的值設計
經常使用操做:指針
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; void preorder(bintree t) { if (t) { printf("%c", t->data); preorder(t->lchild); preorder(t->rchild); } }
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; bintree createbintree() { char ch; bintree t; if ((ch = getchar()) == '#') t = NULL; else { t = (bintnode *) malloc(sizeof(bintnode)); // 生成二叉樹的根結點 t->data = ch; t->lchild = createbintree(); // 遞歸實現左子樹的創建 t->rchild = createbintree(); // 遞歸實現右子樹的創建 } return t; }
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; void preorder1(bintree t) { seqstack s; s.top = 0; // 當前處理的子樹不爲空或棧不爲空則循環 while ((t) || (s.top != 0)) { if (t) { printf("%c ", t->data); push(&s, t); t = t->lchild; } else { t = pop(&s); t = t->rchlid; } } }
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; bintree locate(bintree t, dataype x) { bintree p; if (t == NULL) return NULL; else { if (t->data == x) return t; else { p = locate(t->lrchild); if (p) return p; else return locate(t->rchild) } } }
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; int numofnode(bintree t) { if (t == NULL) return 0; else return (numofnode(t->lchild) + numofnode(t->rchild) + 1); }
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; int isequal(bintree t1, bintree t2) { int t; t = 0; if (t1 == NULL && t2 == NULL) t = 1; // t1 和 t2 均爲空,則兩者等價 else { // 處理 t1 和 t2 均不爲空的狀況 if (t1 != NUll && t2 != NULL) if (t1->data == t2->data) // 若是根結點的值相等 if (isequeal(t1->lchild, t2->lchild)) // 若是 t1 和 t2 的左子樹等價 t = isequeal(t1->rchild, t2->rchild); // 返回值取決於 t1 和 t2 的右子樹是否等價 } return (t); }
typedef char datatype; // 結點屬性值的類型 // 二叉樹結點的類型 typedef struct node { datatype data; struct node *lchild, *rchild; } bintnode; typedef bintnode *bintree; int depth(bintree t) { int h, lh, rh; if (t == NULL) h = 0; // 處理空二叉樹的狀況 else { lh = depth(t->lchild); // 求左子樹的高度 rh = depth(t->rchild); // 求右子樹的高度 if (lh >= rh) h = lh + 1; // 求二叉樹t的高度 else h = rh + 1; } return h; }
穿線二叉樹的指針:結點的左、右指針指向其左、右子女code
中序穿線二叉樹的線索:結點的左、右指針指向其中序遍歷的前驅、後繼結點blog
爲了區別結點的左右指針是指針仍是線索,通常加上 \(ltag\) 和 \(rtag\) 兩個標誌位遞歸
圖中序穿線二叉樹:get
typedef char datatype; typedef struct node { datatype data; int ltag, rtag; // 左右標誌位 struct node *lchild, *rchild; } binthrnode; typedef binthrnode *binthrtree;
typedef char datatype; typedef struct node { datatype data; int ltag, rtag; // 左右標誌位 struct node *lchild, *rchild; } binthrnode; typedef binthrnode *binthrtree; // 尋找結點 p 在中序遍歷下的後繼結點 binthrtree insuccnode(binthrtree p) { binthrtree q; if (p->rtag == 1) // p 的右指針爲線索,恰巧指向p的後繼結點 return p->rchild; else { q = p->rchild; // 尋找 p 的右子樹中最左下的結點 while (q->ltag == 0) q = q->lchild; // 求該右子樹下中序遍歷下的第一個結點 return q; } } // 中序遍歷中序穿線二叉樹 void inthrtree(binthrtree p) { if (p) { while (p->ltag == 0) p = p->lchild; // 求 p 中序遍歷下的第一個結點 do { printf("%c ", p->data); p = insuccnode(p); // 求 p 中序遍歷下的後繼結點 } while (p); } }
樹、森林到二叉樹的轉換步驟
圖樹到二叉樹的轉換:
圖森林到二叉樹的轉換:
首先將二叉樹按照逆時針方向旋轉45度
若某結點是其雙親的左子女,則把該結點的右子女,右子女的右子女,……都與該結點的雙親用線連起來
最後去掉原二叉樹中全部雙親到其右子女的連線
注:最後鏈接子結點,只能鏈接右子女,而不能鏈接左子女
圖二叉樹到森林的轉換:
根據前序序列的第一個元素創建根結點;
在中序序列中找到該元素,肯定根結點的左右子樹的中序序列;
在前序序列中肯定左右子樹的前序序列;
由左子樹的前序序列和中序序列創建左子樹;
由右子樹的前序序列和中序序列創建右子樹。
如:已知一棵二叉樹的先序遍歷序列和中序遍歷序列分別是 abdgcefh、dgbaechf,求二叉樹及後序遍歷序列。 先序:abdgcefh—>a bdg cefh 中序:dgbaechf—->dgb a echf 得出結論:a 是樹根,a 有左子樹和右子樹,左子樹有 bdg 結點,右子樹有 cefh 結點 先序:bdg—>b dg 中序:dgb —>dg b 得出結論:b 是左子樹的根結點,b 無右子樹,有左子樹 先序:dg—->d g 中序:dg—–>dg 得出結論:d 是 b 左子樹的根節點,d 無左子樹,g 是 d 的右子樹 而後對於 a 的右子樹相似能夠推出 而後還原
如:已知一棵二叉樹的後序遍歷序列和中序遍歷序列分別是gdbehfca、dgbaechf,求二叉樹 後序:gdbehfca—->gdb ehfc a 中序:dgbaechf—–>dgb a echf 得出結論:a是樹根,a有左子樹和右子樹,左子樹有 bdg 結點,右子樹有 cefh 結點 後序:gdb—->gd b 中序:dgb—–>dg b 得出結論:b 是 a 左子樹的根節點,無右子樹,有左子樹 dg 後序:gd—->g d 中序:dg—–>d g 得出結論:d 是 b 的左子樹根節點,g 是 d 的右子樹 而後對於 a 的右子樹相似能夠推出 而後還原
分別採用遞歸和非遞歸方式編寫兩個函數,求一棵給定二叉樹中葉子結點的個數
typedef char datatype; typedef struct node { datatype data; struct node *lchild, *rchild; } binthrnode; typedef binthrnode *bintree; // 遞歸方法求二叉樹葉子結點的個數 int leaf1(bintree t) { if (t == NULL) return 0; else if (!t->lchild && !t->rchild) return 1; else return leaf1(t->lchild) + leaf1(t->rchild); } // 非遞歸方法求二叉樹葉子結點的個數 int leaf2(bintree t) { seqstack s; // 順序棧 int count = 0; // 葉子結點計數變量 init(&s); // 初始化空棧 while (t || !empty(&s)) { if (t) { if (!t->lchild && !t->rchild) count++; push(&s, t); t = t->lchild; } else { t = pop(&s); t = t->rchild; } } return count; }
試編寫一個函數,返回一顆給定二叉樹在中序遍歷下的最後一個結點
typedef char datatype; typedef struct node { datatype data; struct node *lchild, *rchild; } binthrnode; typedef binthrnode *bintree; // 遞歸實現 bintree midlast(bintree t) { if (t && t->rchild) t = midlast(t->rchild); return t; } // 非遞歸實現 bintree midlast(bintree t) { bintree p = t; while (p && p->rchild) p = p->rchild; return p; }
前序(根左右)和中序(左根右)遍歷結果相同的二叉樹(去掉左都爲「根右」)爲(全部結點只有右子樹的二叉樹);前序(根左右)和後序(左右根)遍歷結果相同的二叉樹(哪個子樹都不能夠去掉)爲(只有根結點的二叉樹)
有 \(n\) 個結點的二叉樹,已知葉結點個數爲 \(n_0\),則該樹中度爲 \(1\) 的結點的個數爲(\(n-2*n_0+1\));若此樹是深度爲 \(k\) 的徹底二叉樹,則 \(n\) 的最小值爲 (\(2^{k-1}\))
(真題)對於一顆具備 \(n\) 個結點的二叉樹,該二叉樹中全部結點的讀書之和爲(\(n-1\))
(真題)試分別畫出具備 \(3\) 個結點的樹和具備 \(3\) 個結點的二叉樹的全部不一樣形態。(此題注意樹具備無序性)