刚开始接触图论这一模块是觉得什么二叉树啊,什么堆啊,什么优先队列啊这些东西很难搞,终于等到放假了,抱着本算法书,发现和教练说的一样,树是一种很神奇很简单的东西,很讨人喜欢。
二叉树的性质:
性质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 ", 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 ", 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 }