剛開始接觸圖論這一模塊是覺得什么二叉樹啊,什么堆啊,什么優先隊列啊這些東西很難搞,終於等到放假了,抱着本算法書,發現和教練說的一樣,樹是一種很神奇很簡單的東西,很討人喜歡。
二叉樹的性質:
性質1:二叉樹上結點數等於度為 2 的結點數加 1;
性質2:二叉樹的第 i 層上至多有 2^( i-1 ) 個結點( i >= 1;
性質3:對於完全二叉樹中編號為 i 的結點( 1 <= i <= N, N>= 1, N為結點數 ),有:
(1)若 2*i <= N, 則編號為 i 的結點為分支結點, 否則為葉子結點。
(2)若 N 為奇數, 則每個分支結點都既有左孩子,又有右孩子;若 N 為偶數, 則編號最大的分支結點(編號為 N/2 )只有左孩子沒有右孩子,其余分支結 點都既有左孩子,又有右孩子
建立二叉樹結點數據的規則:
(1)以第一個建立的元素為根結點;
(2)依序將元素值與根結點進行比較
①若元素值大於根結點值,則將元素值往根結點的右子結點移動,若此右子結點為空,則將元素值存入,否則就重復比較直到找到合適的空結點;
②若元素值小於根結點值,則將元素值往根結點的左子結點移動,若此左子結點為空,則將元素值存入,否則就重復比較直到找到合適的空結點;
(上述的建立二叉樹結點數據的規則滿足了二叉排序樹(二叉查找樹)的條件)
這里包括三種建二叉樹的簡單方法:
一、一維數組表示法(優點簡單粗暴,缺點維護這棵樹不容易,牽一發而動全身)
二、結構數組表示法(同上)
///數組表示法 /* #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAXN = 32768; ///2^5 int tree[MAXN]; ///所有數組均從1開始 int create(int _tree[], int _node[], int len) { int i, MAX = 1; _tree[1] = _node[1]; int level = 1; for(int i = 2; i <= len; i++) { level = 1; while(_tree[level] != 0) ///判斷當前位置是否有值 { if(_node[i] < _tree[level]) ///左子樹 level = level*2; else ///右子樹 level = level*2+1; if(MAX < level) ///更新樹數組的最大下標 MAX = level; } _tree[level] = _node[i]; ///給結點賦值 } return MAX; } int main() { int N, num; scanf("%d", &N); int node[N+1]; for(int i = 1; i <= N; i++) scanf("%d", &node[i]); num = create(tree, node, N); ///建樹 for(int i = 1; i <= num-1; i++) printf("%d ", tree[i]); printf("%d\n", tree[num]); return 0; } */ ///結構數組表示法 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAXN = 32768; struct tree { int left; int date; int right; }b_tree[MAXN]; int N; typedef struct tree treenode; void create(int *node, int len) { int i; int level; int position; ///左樹-1, 右樹1 for(int i = 1; i <= len; i++) ///依次建立其他結點 { b_tree[i].date = node[i]; ///元素值存入結點 level = 0; ///樹根為0 position = 0; while(position == 0) { if(node[i] > b_tree[level].date) ///判斷是否為右子樹 { if(b_tree[level].right != -1) level = b_tree[level].right; else position = -1; } else ///判斷是否為左子樹 { if(b_tree[level].left != -1) level = b_tree[level].left; else position = 1; } } if(position == 1) ///連接左子樹 b_tree[level].left = i; else b_tree[level].right = i; ///連接右子樹 } } void print() { for(int i = 1; i <= N; i++) { printf("%d %d %d\n", b_tree[i].left, b_tree[i].date, b_tree[i].right); } } int main() { scanf("%d", &N); int node[N+1]; for(int i = 1;i <= N; i++) scanf("%d", &node[i]); for(int i = 0; i < MAXN; i++) { b_tree[i].left = -1; b_tree[i].date = 0; b_tree[i].right = -1; } create(node, N); print(); return 0; }
三、鏈表表示法(按前序遍歷輸出)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct tree 5 { 6 struct tree *left; 7 int date; 8 struct tree *right; 9 }; 10 typedef struct tree treenode; 11 typedef struct tree * b_tree; 12 13 b_tree add(b_tree root, int node) ///插入結點+ 14 { 15 b_tree newnode; 16 b_tree currentnode; 17 b_tree parentnode; 18 19 newnode = (b_tree)malloc(sizeof(treenode)); 20 newnode->date = node; 21 newnode->left = NULL; 22 newnode->right = NULL; 23 24 if(root == NULL) ///第一個結點建立 25 return newnode; 26 else 27 { 28 currentnode = root; ///儲存當前結點 29 while(currentnode != NULL) ///當前結點不為空 30 { 31 parentnode = currentnode; ///儲存父結點 32 if(currentnode->date > node) 33 currentnode = currentnode->left; ///左子樹 34 else 35 currentnode = currentnode->right; ///右子樹 36 } 37 if(parentnode->date > node) 38 parentnode->left = newnode; 39 else 40 parentnode->right = newnode; 41 } 42 return root; 43 } 44 45 b_tree create(int *data, int len) 46 { 47 int i; 48 b_tree root = NULL; 49 for(int i = 1; i <= len; i++) 50 { 51 root = add(root, data[i]); 52 } 53 return root; 54 } 55 56 void print(b_tree root) 57 { 58 if(root != NULL) 59 { 60 cout << root->date << ' '; 61 print(root->left); 62 print(root->right); 63 } 64 } 65 66 int main() 67 { 68 int N; 69 b_tree root = NULL; 70 cin >> N; 71 int node[N+1]; 72 for(int i = 1; i <= N; i++) 73 cin >> node[i]; 74 root = create(node, N); 75 print(root); 76 cout << endl; 77 return 0; 78 }