二叉樹的二叉鏈表表示與實現


http://blog.csdn.net/algorithm_only/article/details/6973848

前面幾節講到的結構都是一種線性的數據結構,今天要說到另外一種數據結構——樹,其中二叉樹最為常用。二叉樹的特點是每個結點至多只有兩棵子樹,且二叉樹有左右字子樹之分,次序不能任意顛倒。

二叉樹的存儲結構可以用順序存儲和鏈式存儲來存儲。二叉樹的順序存儲結構由一組連續的存儲單元依次從上到下,從左到右存儲完全二叉樹的結點元素。對於一般二叉樹,應將其與完全二叉樹對應,然后給每個結點從1到i編上號,依次存儲在大小為i-1的數組中。這種方法只適用於完全二叉樹,對非完全二叉樹會浪費較多空間,最壞情況一個深度為k的二叉樹只有k個結點,卻需要長度為2的k次方減一長度的一位數組。事實上,二叉樹一般使用鏈式存儲結構,由二叉樹的定義可知,二叉樹的結點由一個數據元素和分別指向其左右孩子的指針構成,即二叉樹的鏈表結點中包含3個域,這種結點結構的二叉樹存儲結構稱之為二叉鏈表

  • 二叉鏈表的存儲結構

 

 
 
 
         typedef struct tnode {
    elemtype data;
    struct tnode *lchild;
    struct tnode *rchild;
}*bitree, bitnode;
 
 
 
         

 

  • 創建一棵二叉樹(按先序序列建立)
 1 int create_bitree(bitree *bt)
 2 {
 3     elemtype    data;
 4 
 5     scanf("%d", &data);
 6     if (0 == data) {
 7         *bt = NULL;
 8     } else {
 9         *bt = (bitree)malloc(sizeof(bitnode));
10         if (!(*bt))
11             exit(OVERFLOW);
12         (*bt)->data = data;
13         create_bitree(&(*bt)->lchild);
14         create_bitree(&(*bt)->rchild);
15     }
16     return OK;
17 }
View Code
按先序次序輸入二叉樹的結點值,0表示空樹。
  • 二叉樹的遍歷(先序、中序、后序)
 1 void preorder(bitree bt, int (*visit)(elemtype e))
 2 {
 3     if (bt) {
 4         visit(bt->data);
 5         preorder(bt->lchild, visit);
 6         preorder(bt->rchild, visit);
 7     }
 8 }
 9 
10 
11 void inorder(bitree bt, int (*visit)(elemtype e))
12 {
13     if (bt) {
14         inorder(bt->lchild, visit);
15         visit(bt->data);
16         inorder(bt->rchild, visit);
17     }
18 }
19 
20 void postorder(bitree bt, int (*visit)(elemtype e))
21 {
22     if (bt) {
23         postorder(bt->lchild, visit);
24         postorder(bt->rchild, visit);
25         visit(bt->data);
26     }
27 }
View Code

二叉樹的遞歸算法較簡單,代碼簡潔清晰,但遞歸算法效率低,執行速度慢,在下一節將說到二叉樹非遞歸遍歷算法。

  • 求二叉樹的深度
 1 int get_tree_depth(bitree bt)
 2 {
 3     int ldepth, rdepth;
 4 
 5     if (!bt)
 6         return 0;
 7     else if (!bt->lchild && !bt->rchild)
 8         return 1;
 9     else {
10         ldepth = get_tree_depth(bt->lchild);
11         rdepth = get_tree_depth(bt->rchild);
12 
13         return (ldepth > rdepth ? ldepth : rdepth) + 1;
14     }
15 }
View Code

樹的深度即樹的結點中最大層次,分別遞歸求左右子樹的深度,較大子樹深度為樹的深度。

  • 求葉子結點數
1 int get_num_of_leave(bitree bt)
2 {
3 if (!bt)
4 return 0;
5 else if (!bt->lchild && !bt->rchild)
6 return 1;
7 else
8 return (get_num_of_leave(bt->lchild) + get_num_of_leave(bt->rchild));
9 }

 

 

遞歸求左右子樹的葉子數,左右子樹的葉子結點之和為樹的葉子結點數。
  • 釋放二叉樹
 1 void free_bitree(bitree *bt)  
 2 {  
 3     if (*bt) {  
 4         if ((*bt)->lchild)  
 5             free_bitree(&(*bt)->lchild);  
 6         if ((*bt)->rchild)  
 7             free_bitree(&(*bt)->rchild);  
 8             free(*bt);  
 9             *bt = NULL;  
10     }  
11 }

 

全部實現:

 

  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include <string>
  4 #include <string.h>
  5 #include <iostream>
  6 #include <vector>
  7 #include <stack>
  8 using namespace std;
  9 #define debug(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
 10 typedef char elemtype;
 11 //二叉鏈表結構
 12 typedef struct tnode {
 13     elemtype data;
 14     struct tnode *lchild;
 15     struct tnode *rchild;
 16 }*bitree, bitnode;
 17 
 18 int create_bitree(bitree *bt)
 19 {
 20     elemtype data;
 21     scanf("%c", &data);
 22     if ('#' == data) {
 23         *bt = NULL;
 24     } else {
 25         *bt = (bitree)malloc(sizeof(bitnode));
 26         if (!(*bt))
 27             perror("bt malloc");
 28         (*bt)->data = data;
 29         create_bitree(&(*bt)->lchild);
 30         create_bitree(&(*bt)->rchild);
 31     }
 32     return 1;
 33 }
 34 
 35 void preorder(bitree bt, int (*visit)(elemtype e))
 36 {
 37     if (bt) {
 38         visit(bt->data);
 39         preorder(bt->lchild, visit);
 40         preorder(bt->rchild, visit);
 41     }
 42 }
 43 
 44 
 45 void inorder(bitree bt, int (*visit)(elemtype e))
 46 {
 47     if (bt) {
 48         inorder(bt->lchild, visit);
 49         visit(bt->data);
 50         inorder(bt->rchild, visit);
 51     }
 52 }
 53 
 54 void postorder(bitree bt, int (*visit)(elemtype e))
 55 {
 56     if (bt) {
 57         postorder(bt->lchild, visit);
 58         postorder(bt->rchild, visit);
 59         visit(bt->data);
 60     }
 61 }
 62 
 63 int print(elemtype e){
 64     printf("%c", e);
 65     return 1;
 66 }
 67 
 68 int get_tree_depth(bitree bt)
 69 {
 70     int ldepth, rdepth;
 71 
 72     if (!bt)
 73         return 0;
 74     else if (!bt->lchild && !bt->rchild)
 75         return 1;
 76     else {
 77         ldepth = get_tree_depth(bt->lchild);
 78         rdepth = get_tree_depth(bt->rchild);
 79 
 80         return (ldepth > rdepth ? ldepth : rdepth) + 1;
 81     }
 82 }
 83 
 84 void free_bitree(bitree *bt)
 85 {
 86     if (*bt) {
 87         if ((*bt)->lchild)
 88             free_bitree(&(*bt)->lchild);
 89         if ((*bt)->rchild)
 90             free_bitree(&(*bt)->rchild);
 91             free(*bt);
 92             *bt = NULL;
 93     }
 94 }
 95 typedef int (*func)(bitree bt);
 96 int main(void) {
 97     bitree bt;
 98     create_bitree(&bt);
 99     printf("pre:");
100     preorder(bt, print);
101     printf("\n");
102     printf("in:");
103     inorder(bt, print);
104     printf("\n");
105     printf("post:");
106     postorder(bt, print);
107     printf("\n");
108     free_bitree(&bt);
109     return 0;
110 }
View Code

 

 

 

2016-11-16 22:05:10

最低公共祖先節點

  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include <error.h>
  4 #include <iostream>
  5 #include <string>
  6 #include <vector>
  7 #include <stack>
  8 #include <unistd.h>
  9 #include <time.h>
 10 using namespace std;
 11 #define debug(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
 12 typedef char elemtype;
 13 typedef struct Bitree{
 14     elemtype data;
 15     struct Bitree *lchild;
 16     struct Bitree *rchild;
 17 }STBitree,*bitree;
 18 
 19 vector<STBitree *>::iterator vbi;
 20 vector<elemtype>::iterator vei;
 21 
 22 //前序創建二叉樹
 23 STBitree *precreate();
 24 //打印二叉樹
 25 int print_bitree(elemtype e);
 26 //遞歸-前序,中序,后序遍歷二叉樹
 27 void preorder(bitree bt, int (*visit)(elemtype e));
 28 void inorder(bitree bt, int (*visit)(elemtype e));
 29 void postorder(bitree bt, int (*visit)(elemtype e));
 30 //非遞歸-前序,中序,后序遍歷二叉樹
 31 void nrpreorder(bitree root);
 32 void nrinorder(bitree root);
 33 void nrpostorder(bitree root);
 34 void nrpostorderfunc(bitree root, int (*visit)(elemtype e));
 35 //根到某個子節點的路徑
 36 vector<elemtype> rc_path(bitree root, elemtype ekey);
 37 //最低公共祖先節點
 38 elemtype lca(STBitree *root,  elemtype node1, elemtype node2);
 39 //釋放二叉樹
 40 void free_bitree(STBitree *bt);
 41 
 42 int main()
 43 {
 44     STBitree *root;
 45     //printf("%lu %lu\n", sizeof(STBitree),sizeof(bitree));
 46     cout << "create biBtree:";
 47     root = precreate();
 48     vector<elemtype> ve;
 49     lca(root, 'd','c');
 50 //    cout << "preorder:";
 51 //    preorder(root, print_bitree);
 52 //    cout << '\n';
 53 //    cout << "inorder:";
 54 //    inorder(root, print_bitree);
 55 //    cout << '\n';
 56 //    cout << "postorder:";
 57 //    postorder(root, print_bitree);
 58 //    cout << '\n';
 59 //    cout << "nrpostorder:";
 60 //    nrpostorderfunc(root, print_bitree);
 61 //    cout << '\n';
 62     free_bitree(root);
 63 }
 64 
 65 STBitree *precreate(){
 66     STBitree *root;
 67     char ch;
 68     scanf("%c", &ch);
 69     if(ch == '#'){
 70         root = NULL;
 71     }
 72     else {
 73         root = (STBitree *)malloc(sizeof(STBitree));
 74         root->data = ch;
 75         root->lchild=precreate();
 76         root->rchild=precreate();
 77     }
 78     return root;
 79 }
 80 
 81 int print_bitree(elemtype e){
 82     cout << e;
 83     return 0;
 84 }
 85 
 86 void preorder(bitree bt, int (*visit)(elemtype e))
 87 {
 88     if (bt) {
 89         visit(bt->data);
 90         preorder(bt->lchild, visit);
 91         preorder(bt->rchild, visit);
 92     }
 93 }
 94 
 95 void inorder(bitree bt, int (*visit)(elemtype e))
 96 {
 97     if (bt) {
 98         inorder(bt->lchild, visit);
 99         visit(bt->data);
100         inorder(bt->rchild, visit);
101     }
102 }
103 
104 void postorder(bitree bt, int (*visit)(elemtype e))
105 {
106     if (bt) {
107         postorder(bt->lchild, visit);
108         postorder(bt->rchild, visit);
109         visit(bt->data);
110     }
111 }
112 
113 vector<elemtype> rc_path(bitree root, elemtype ekey){
114     stack<bitree> sbt;
115     bitree pCur, pLastVisit;
116     vector<elemtype> ve;
117     pCur = root;
118     pLastVisit = NULL;
119     ve.clear();
120     while (pCur) {
121         sbt.push(pCur);
122         ve.push_back(pCur->data);
123         pCur = pCur->lchild;
124     }
125 
126     while (!sbt.empty()) {
127         pCur = sbt.top();
128         sbt.pop();
129         ve.pop_back();
130         if(pCur->rchild == NULL || pLastVisit == pCur->rchild){
131             if(pCur->data == ekey){
132                 ve.push_back(pCur->data);
133 //                for (vei = ve.begin(); vei != ve.end(); ++vei) {
134 //                    cout << *vei ;
135 //                }
136                 return ve;
137             }
138             pLastVisit = pCur;
139         }
140         if(pCur->lchild == pLastVisit){
141             sbt.push(pCur);
142             ve.push_back(pCur->data);
143             pCur = pCur->rchild;
144             while (pCur) {
145                 sbt.push(pCur);
146                 ve.push_back(pCur->data);
147                 pCur = pCur->lchild;
148             }
149         }
150     }
151 }
152 
153 elemtype lca(STBitree *root, elemtype node1, elemtype node2){
154     vector<STBitree *> vb;
155     vector<elemtype> ve1;
156     vector<elemtype> ve2;
157     vb.clear();
158     if(root == NULL){
159         return 0;
160     }
161     ve1 = rc_path(root, node1);
162     ve2 = rc_path(root, node2);
163     int idx = 0,preidx = 0;
164     while (ve1[idx] == ve2[idx]) {
165         ++idx;
166     }
167     --idx;
168     cout << ve1[idx];
169     return ve1[idx];
170 }
171 
172 void nrpostorder(bitree root){
173     stack<bitree> sbt;// ab#deg###f#h##c##
174     //pCur當前訪問節點,pLastVisit上次訪問節點  // ab#de##f##c##
175     bitree pCur,pLastVisit;
176     if (root == NULL) {
177         return;
178     }
179     pCur = root;
180     pLastVisit = NULL;
181     while (pCur) {
182         sbt.push(pCur);
183         //vb.push_back(pCur);
184         pCur = pCur->lchild;
185     }
186 //    cout << "[從根到最左節點:";
187 //    for (vbi = vb.begin(); vbi != vb.end(); ++vbi) {
188 //        cout << (*vbi)->data;
189 //    }
190 //    cout << "]\n";
191     while (!sbt.empty()) {
192         pCur = sbt.top();
193         //debug(pCur);
194         sbt.pop();//ab#d##c##
195         //        vb.pop_back();
196         //        cout << "前棧中元素:";
197         //        for (vbi = vb.begin(); vbi != vb.end(); ++vbi) {
198         //            cout << (*vbi)->data << endl;
199         //        }
200         //        cout << '\n';
201         //當前節點的右孩子是上次訪問的節點pl或者當前節點的右孩子為空,則說明說明可以直接訪問該節點了.
202         if((pLastVisit == pCur->rchild) || (pCur->rchild == NULL)){
203             cout << pCur->data;
204             pLastVisit = pCur;
205         }
206         if(pCur->lchild == pLastVisit){
207             sbt.push(pCur);
208             pCur = pCur->rchild;
209             while (pCur) {
210                 sbt.push(pCur);
211                 pCur = pCur->lchild;
212             }
213         }
214         //N@20161118
215         //        if(pCur->rchild != NULL){
216         //            if(pLastVisit != pCur->rchild){
217         //                sbt.push(pCur);
218         //                pCur = pCur->rchild;
219         //                while (pCur) {
220         //                    sbt.push(pCur);
221         //                    pCur = pCur->lchild;
222         //                }
223         //            }
224         //        }
225         //        cout << "后棧中元素:";
226         //        for (vbi = vb.begin(); vbi != vb.end(); ++vbi) {
227         //            cout << (*vbi)->data << endl;
228         //        }
229         //        cout << '\n';
230     }
231 }
232 
233 void nrpostorderfunc(bitree root, int (*visit)(elemtype e)){
234     stack<bitree> sbt;// ab#deg###f#h##c##
235     //pCur當前訪問節點,pLastVisit上次訪問節點  // ab#de##f##c##
236     bitree pCur,pLastVisit;
237     if (root == NULL) {
238         return;
239     }
240     pCur = root;
241     pLastVisit = NULL;
242     while (pCur) {
243         sbt.push(pCur);
244         //vb.push_back(pCur);
245         pCur = pCur->lchild;
246     }
247 //    cout << "[從根到最左節點:";
248 //    for (vbi = vb.begin(); vbi != vb.end(); ++vbi) {
249 //        cout << (*vbi)->data;
250 //    }
251 //    cout << "]\n";
252     while (!sbt.empty()) {
253         pCur = sbt.top();
254         //debug(pCur);
255         sbt.pop();//ab#d##c##
256         //        vb.pop_back();
257         //        cout << "前棧中元素:";
258         //        for (vbi = vb.begin(); vbi != vb.end(); ++vbi) {
259         //            cout << (*vbi)->data << endl;
260         //        }
261         //        cout << '\n';
262         //當前節點的右孩子是上次訪問的節點pl或者當前節點的右孩子為空,則說明說明可以直接訪問該節點了.
263         if((pLastVisit == pCur->rchild) || (pCur->rchild == NULL)){
264             //cout << pCur->data;
265            visit(pCur->data);
266             pLastVisit = pCur;
267         }
268         if(pCur->lchild == pLastVisit){
269             sbt.push(pCur);
270             pCur = pCur->rchild;
271             while (pCur) {
272                 sbt.push(pCur);
273                 pCur = pCur->lchild;
274             }
275         }
276         //N@20161118
277         //        if(pCur->rchild != NULL){
278         //            if(pLastVisit != pCur->rchild){
279         //                sbt.push(pCur);
280         //                pCur = pCur->rchild;
281         //                while (pCur) {
282         //                    sbt.push(pCur);
283         //                    pCur = pCur->lchild;
284         //                }
285         //            }
286         //        }
287         //        cout << "后棧中元素:";
288         //        for (vbi = vb.begin(); vbi != vb.end(); ++vbi) {
289         //            cout << (*vbi)->data << endl;
290         //        }
291         //        cout << '\n';
292     }
293 }
294 
295 void free_bitree(STBitree *bt)
296 {
297     if (bt) {
298         if ((*bt).lchild)
299             free_bitree((*bt).lchild);
300         if ((*bt).rchild)
301             free_bitree((*bt).rchild);
302         free(bt);
303         bt = NULL;
304     }
305 }
View Code

 

Method 1 (By Storing root to n1 and root to n2 paths):
Following is simple O(n) algorithm to find LCA of n1 and n2.
1) Find path from root to n1 and store it in a vector or array.
2) Find path from root to n2 and store it in another vector or array.
3) Traverse both paths till the values in arrays are same. Return the common element just before the mismatch.

 1 // http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/
 2 // A O(n) solution to find LCA of two given values n1 and n2
 3 #include <iostream>
 4 #include <vector>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 // A Bianry Tree node
 9 struct Node
10 {
11     int key;
12     struct Node *left, *right;
13 };
14 
15 struct myclass {           // function object type:
16   void operator() (int i) {std::cout << ' ' << i;}
17 } myobject;
18 
19 // Utility function creates a new binary tree node with given key
20 Node * newNode(int k)
21 {
22     Node *temp = new Node;
23     temp->key = k;
24     temp->left = temp->right = NULL;
25     return temp;
26 }
27 
28 // Finds the path from root node to given root of the tree, Stores the
29 // path in a vector path[], returns true if path exists otherwise false
30 bool findPath(Node *root, vector<int> &path, int k)
31 {
32     // base case
33     if (root == NULL) return false;
34 
35     // Store this node in path vector. The node will be removed if
36     // not in path from root to k
37     path.push_back(root->key);
38 
39     // See if the k is same as root's key
40     if (root->key == k)
41         return true;
42 
43     // Check if k is found in left or right sub-tree
44     if ( (root->left && findPath(root->left, path, k)) ||
45         (root->right && findPath(root->right, path, k)) )
46         return true;
47 
48     // If not present in subtree rooted with root, remove root from
49     // path[] and return false
50     path.pop_back();
51     return false;
52 }
53 
54 // Returns LCA if node n1, n2 are present in the given binary tree,
55 // otherwise return -1
56 int findLCA(Node *root, int n1, int n2)
57 {
58     // to store paths to n1 and n2 from the root
59     vector<int> path1, path2;
60 
61     // Find paths from root to n1 and root to n1. If either n1 or n2
62     // is not present, return -1
63     if ( !findPath(root, path1, n1) || !findPath(root, path2, n2))
64         return -1;
65 
66     /* Compare the paths to get the first different value */
67     size_t i;
68     for (i = 0; i < path1.size() && i < path2.size() ; i++)
69         if (path1[i] != path2[i])
70             break;
71     return path1[i-1];
72 }
73 
74 // Driver program to test above functions
75 int main()
76 {
77     // Let us create the Binary Tree shown in above diagram.
78     Node * root = newNode(1);
79     root->left = newNode(2);
80     root->right = newNode(3);
81     root->left->left = newNode(4);
82     root->left->right = newNode(5);
83     root->right->left = newNode(6);
84     root->right->right = newNode(7);
85     cout << "LCA(4, 5) = " << findLCA(root, 4, 5);
86     cout << "\nLCA(4, 6) = " << findLCA(root, 4, 6);
87     cout << "\nLCA(3, 4) = " << findLCA(root, 3, 4);
88     cout << "\nLCA(2, 4) = " << findLCA(root, 2, 4);
89     return 0;
90 }
View Code

 

只遍歷一遍二叉樹的方法:

/* Program to find LCA of n1 and n2 using one traversal of Binary Tree.
It handles all cases even when n1 or n2 is not there in Binary Tree */
#include <iostream>
using namespace std;

// A Binary Tree Node
struct Node
{
    struct Node *left, *right;
    int key;
};

// Utility function to create a new tree Node
Node* newNode(int key)
{
    Node *temp = new Node;
    temp->key = key;
    temp->left = temp->right = NULL;
    return temp;
}

// This function returns pointer to LCA of two given values n1 and n2.
// v1 is set as true by this function if n1 is found
// v2 is set as true by this function if n2 is found
struct Node *findLCAUtil(struct Node* root, int n1, int n2, bool &v1, bool &v2)
{
    // Base case
    if (root == NULL) return NULL;

    // If either n1 or n2 matches with root's key, report the presence
    // by setting v1 or v2 as true and return root (Note that if a key
    // is ancestor of other, then the ancestor key becomes LCA)
    if (root->key == n1)
    {
        v1 = true;
        return root;
    }
    if (root->key == n2)
    {
        v2 = true;
        return root;
    }

    // Look for keys in left and right subtrees
    Node *left_lca = findLCAUtil(root->left, n1, n2, v1, v2);
    Node *right_lca = findLCAUtil(root->right, n1, n2, v1, v2);

    // If both of the above calls return Non-NULL, then one key
    // is present in once subtree and other is present in other,
    // So this node is the LCA
    if (left_lca && right_lca) return root;

    // Otherwise check if left subtree or right subtree is LCA
    return (left_lca != NULL)? left_lca: right_lca;
}

// Returns true if key k is present in tree rooted with root
bool find(Node *root, int k)
{
    // Base Case
    if (root == NULL)
        return false;

    // If key is present at root, or in left subtree or right subtree,
    // return true;
    if (root->key == k || find(root->left, k) || find(root->right, k))
        return true;

    // Else return false
    return false;
}

// This function returns LCA of n1 and n2 only if both n1 and n2 are present
// in tree, otherwise returns NULL;
Node *findLCA(Node *root, int n1, int n2)
{
    // Initialize n1 and n2 as not visited
    bool v1 = false, v2 = false;

    // Find lca of n1 and n2 using the technique discussed above
    Node *lca = findLCAUtil(root, n1, n2, v1, v2);

    // Return LCA only if both n1 and n2 are present in tree
    if (v1 && v2 || v1 && find(lca, n2) || v2 && find(lca, n1))
        return lca;

    // Else return NULL
    return NULL;
}

// Driver program to test above functions
int main()
{
    // Let us create binary tree given in the above example
    Node * root = newNode(1);
    root->left = newNode(2);
    root->right = newNode(3);
    root->left->left = newNode(4);
    root->left->right = newNode(5);
    root->right->left = newNode(6);
    root->right->right = newNode(7);
    Node *lca = findLCA(root, 4, 5);
    if (lca != NULL)
    cout << "LCA(4, 5) = " << lca->key;
    else
    cout << "Keys are not present ";

    lca = findLCA(root, 4, 10);
    if (lca != NULL)
    cout << "\nLCA(4, 10) = " << lca->key;
    else
    cout << "\nKeys are not present ";
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM