二叉树的二叉链表表示与实现

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

 

posted @ 2016-09-19 13:14  PKICA  阅读(15170)  评论(0编辑  收藏  举报