大牛博客
http://blog.csdn.net/sjf0115/article/details/8645991
以下全部转自大神博客。。。膜拜!!!!!!!!!!!
树形结构是一类重要的非线性数据结构,其中以树和二叉树最为常用。
二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的 i -1次方个结点;深度为k的二叉树至多有2^(k) -1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的结点数为n2,则n0 = n2 + 1。
二叉树的链式存储结构是一类重要的数据结构,其形式定义如下:
1 //二叉树结点 2 typedef struct BiTNode{ 3 //数据 4 char data; 5 //左右孩子指针 6 struct BiTNode *lchild,*rchild; 7 }BiTNode,*BiTree;
二叉树的创建:
通过读入一个字符串,建立二叉树的算法如下:
1 //按先序序列创建二叉树 2 int CreateBiTree(BiTree &T){ 3 char data; 4 //按先序次序输入二叉树中结点的值(一个字符),‘#’表示空树 5 scanf("%c",&data); 6 if(data == '#'){ 7 T = NULL; 8 } 9 else{ 10 T = (BiTree)malloc(sizeof(BiTNode)); 11 //生成根结点 12 T->data = data; 13 //构造左子树 14 CreateBiTree(T->lchild); 15 //构造右子树 16 CreateBiTree(T->rchild); 17 } 18 return 0; 19 }
二叉树的遍历:
遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。
递归算法:
1 //输出 2 void Visit(BiTree T){ 3 if(T->data != '#'){ 4 printf("%c ",T->data); 5 } 6 } 7 //先序遍历 8 void PreOrder(BiTree T){ 9 if(T != NULL){ 10 //访问根节点 11 Visit(T); 12 //访问左子结点 13 PreOrder(T->lchild); 14 //访问右子结点 15 PreOrder(T->rchild); 16 } 17 } 18 //中序遍历 19 void InOrder(BiTree T){ 20 if(T != NULL){ 21 //访问左子结点 22 InOrder(T->lchild); 23 //访问根节点 24 Visit(T); 25 //访问右子结点 26 InOrder(T->rchild); 27 } 28 } 29 //后序遍历 30 void PostOrder(BiTree T){ 31 if(T != NULL){ 32 //访问左子结点 33 PostOrder(T->lchild); 34 //访问右子结点 35 PostOrder(T->rchild); 36 //访问根节点 37 Visit(T); 38 } 39 }
非递归算法:
<1>先序遍历:
【思路】:访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。
1 /* 先序遍历(非递归) 2 思路:访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。 3 */ 4 void PreOrder2(BiTree T){ 5 stack<BiTree> stack; 6 //p是遍历指针 7 BiTree p = T; 8 //栈不空或者p不空时循环 9 while(p || !stack.empty()){ 10 if(p != NULL){ 11 //存入栈中 12 stack.push(p); 13 //访问根节点 14 printf("%c ",p->data); 15 //遍历左子树 16 p = p->lchild; 17 } 18 else{ 19 //退栈 20 p = stack.top(); 21 stack.pop(); 22 //访问右子树 23 p = p->rchild; 24 } 25 }//while 26 }
<2>中序遍历
【思路】:T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。
先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。
1 void InOrder2(BiTree T){ 2 stack<BiTree> stack; 3 //p是遍历指针 4 BiTree p = T; 5 //栈不空或者p不空时循环 6 while(p || !stack.empty()){ 7 if(p != NULL){ 8 //存入栈中 9 stack.push(p); 10 //遍历左子树 11 p = p->lchild; 12 } 13 else{ 14 //退栈,访问根节点 15 p = stack.top(); 16 printf("%c ",p->data); 17 stack.pop(); 18 //访问右子树 19 p = p->rchild; 20 } 21 }//while 22 }
<3>后序遍历
【思路】:T是要遍历树的根指针,后序遍历要求在遍历完左右子树后,再访问根。需要判断根结点的左右子树是否均遍历过。
1 //后序遍历(非递归) 2 typedef struct BiTNodePost{ 3 BiTree biTree; 4 char tag; 5 }BiTNodePost,*BiTreePost; 6 7 void PostOrder2(BiTree T){ 8 stack<BiTreePost> stack; 9 //p是遍历指针 10 BiTree p = T; 11 BiTreePost BT; 12 //栈不空或者p不空时循环 13 while(p != NULL || !stack.empty()){ 14 //遍历左子树 15 while(p != NULL){ 16 BT = (BiTreePost)malloc(sizeof(BiTNodePost)); 17 BT->biTree = p; 18 //访问过左子树 19 BT->tag = 'L'; 20 stack.push(BT); 21 p = p->lchild; 22 } 23 //左右子树访问完毕访问根节点 24 while(!stack.empty() && (stack.top())->tag == 'R'){ 25 BT = stack.top(); 26 //退栈 27 stack.pop(); 28 BT->biTree; 29 printf("%c ",BT->biTree->data); 30 } 31 //遍历右子树 32 if(!stack.empty()){ 33 BT = stack.top(); 34 //访问过右子树 35 BT->tag = 'R'; 36 p = BT->biTree; 37 p = p->rchild; 38 } 39 }//while 40 }
<4>层次遍历
【思路】:按从顶向下,从左至右的顺序来逐层访问每个节点,层次遍历的过程中需要用队列。
1 //层次遍历 2 void LevelOrder(BiTree T){ 3 BiTree p = T; 4 //队列 5 queue<BiTree> queue; 6 //根节点入队 7 queue.push(p); 8 //队列不空循环 9 while(!queue.empty()){ 10 //对头元素出队 11 p = queue.front(); 12 //访问p指向的结点 13 printf("%c ",p->data); 14 //退出队列 15 queue.pop(); 16 //左子树不空,将左子树入队 17 if(p->lchild != NULL){ 18 queue.push(p->lchild); 19 } 20 //右子树不空,将右子树入队 21 if(p->rchild != NULL){ 22 queue.push(p->rchild); 23 } 24 } 25 }
测试用例:
输入:
ABC##DE#G##F###
输出:
代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 //二叉树结点 5 typedef struct BiTNode{ 6 //数据 7 char data; 8 //左右孩子指针 9 struct BiTNode *lchild,*rchild; 10 }BiTNode,*BiTree; 11 12 //按先序序列创建二叉树 13 int CreateBiTree(BiTree &T){ 14 char data; 15 //按先序次序输入二叉树中结点的值(一个字符),‘#’表示空树 16 scanf("%c",&data); 17 if(data == '#'){ 18 T = NULL; 19 } 20 else{ 21 T = (BiTree)malloc(sizeof(BiTNode)); 22 //生成根结点 23 T->data = data; 24 //构造左子树 25 CreateBiTree(T->lchild); 26 //构造右子树 27 CreateBiTree(T->rchild); 28 } 29 return 0; 30 } 31 //输出 32 void Visit(BiTree T){ 33 if(T->data != '#'){ 34 printf("%c ",T->data); 35 } 36 } 37 //先序遍历 38 void PreOrder(BiTree T){ 39 if(T != NULL){ 40 //访问根节点 41 Visit(T); 42 //访问左子结点 43 PreOrder(T->lchild); 44 //访问右子结点 45 PreOrder(T->rchild); 46 } 47 } 48 //中序遍历 49 void InOrder(BiTree T){ 50 if(T != NULL){ 51 //访问左子结点 52 InOrder(T->lchild); 53 //访问根节点 54 Visit(T); 55 //访问右子结点 56 InOrder(T->rchild); 57 } 58 } 59 //后序遍历 60 void PostOrder(BiTree T){ 61 if(T != NULL){ 62 //访问左子结点 63 PostOrder(T->lchild); 64 //访问右子结点 65 PostOrder(T->rchild); 66 //访问根节点 67 Visit(T); 68 } 69 } 70 /* 先序遍历(非递归) 71 思路:访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。 72 */ 73 void PreOrder2(BiTree T){ 74 stack<BiTree> stack; 75 //p是遍历指针 76 BiTree p = T; 77 //栈不空或者p不空时循环 78 while(p || !stack.empty()){ 79 if(p != NULL){ 80 //存入栈中 81 stack.push(p); 82 //访问根节点 83 printf("%c ",p->data); 84 //遍历左子树 85 p = p->lchild; 86 } 87 else{ 88 //退栈 89 p = stack.top(); 90 stack.pop(); 91 //访问右子树 92 p = p->rchild; 93 } 94 }//while 95 } 96 /* 中序遍历(非递归) 97 思路:T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。 98 先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。 99 */ 100 void InOrder2(BiTree T){ 101 stack<BiTree> stack; 102 //p是遍历指针 103 BiTree p = T; 104 //栈不空或者p不空时循环 105 while(p || !stack.empty()){ 106 if(p != NULL){ 107 //存入栈中 108 stack.push(p); 109 //遍历左子树 110 p = p->lchild; 111 } 112 else{ 113 //退栈,访问根节点 114 p = stack.top(); 115 printf("%c ",p->data); 116 stack.pop(); 117 //访问右子树 118 p = p->rchild; 119 } 120 }//while 121 } 122 123 //后序遍历(非递归) 124 typedef struct BiTNodePost{ 125 BiTree biTree; 126 char tag; 127 }BiTNodePost,*BiTreePost; 128 129 void PostOrder2(BiTree T){ 130 stack<BiTreePost> stack; 131 //p是遍历指针 132 BiTree p = T; 133 BiTreePost BT; 134 //栈不空或者p不空时循环 135 while(p != NULL || !stack.empty()){ 136 //遍历左子树 137 while(p != NULL){ 138 BT = (BiTreePost)malloc(sizeof(BiTNodePost)); 139 BT->biTree = p; 140 //访问过左子树 141 BT->tag = 'L'; 142 stack.push(BT); 143 p = p->lchild; 144 } 145 //左右子树访问完毕访问根节点 146 while(!stack.empty() && (stack.top())->tag == 'R'){ 147 BT = stack.top(); 148 //退栈 149 stack.pop(); 150 printf("%c ",BT->biTree->data); 151 } 152 //遍历右子树 153 if(!stack.empty()){ 154 BT = stack.top(); 155 //访问过右子树 156 BT->tag = 'R'; 157 p = BT->biTree; 158 p = p->rchild; 159 } 160 }//while 161 } 162 //层次遍历 163 void LevelOrder(BiTree T){ 164 BiTree p = T; 165 //队列 166 queue<BiTree> queue; 167 //根节点入队 168 queue.push(p); 169 //队列不空循环 170 while(!queue.empty()){ 171 //对头元素出队 172 p = queue.front(); 173 //访问p指向的结点 174 printf("%c ",p->data); 175 //退出队列 176 queue.pop(); 177 //左子树不空,将左子树入队 178 if(p->lchild != NULL){ 179 queue.push(p->lchild); 180 } 181 //右子树不空,将右子树入队 182 if(p->rchild != NULL){ 183 queue.push(p->rchild); 184 } 185 } 186 } 187 int main() 188 { 189 BiTree T; 190 CreateBiTree(T); 191 printf("先序遍历: "); 192 PreOrder(T); 193 printf(" "); 194 printf("先序遍历(非递归): "); 195 PreOrder2(T); 196 printf(" "); 197 printf("中序遍历: "); 198 InOrder(T); 199 printf(" "); 200 printf("中序遍历(非递归): "); 201 InOrder2(T); 202 printf(" "); 203 printf("后序遍历: "); 204 PostOrder(T); 205 printf(" "); 206 printf("后序遍历(非递归): "); 207 PostOrder2(T); 208 printf(" "); 209 printf("层次遍历: "); 210 LevelOrder(T); 211 printf(" "); 212 return 0; 213 }
弱鸡代码!!
//按照层次建树
1 //Binary tree 2 #include <iostream> 3 #include <stdio.h> 4 #include <malloc.h> 5 using namespace std; 6 const int maxn = 1024; 7 struct Binary{ 8 int data; 9 struct Binary *lchild, *rchild; 10 }; 11 Binary *build(Binary *Btree){ 12 printf("Input -1 exit "); 13 Binary *tree, *queue[maxn]; 14 int x, front = 0, rear = -1; 15 while(scanf("%d", &x) && x != -1){ 16 tree = new Binary; 17 tree -> data = x; 18 tree -> lchild = tree -> rchild = NULL; 19 queue[++rear] = tree; 20 if(rear == 0) Btree = tree; 21 else{ 22 if(tree != NULL && queue[front] != NULL){ 23 if(rear%2 == 1){ 24 queue[front] -> lchild = tree; 25 } 26 else{ 27 queue[front] -> rchild = tree; 28 } 29 } 30 if(rear%2 == 0){ 31 front++; 32 } 33 } 34 } 35 return Btree; 36 } 37 void PreOrder(Binary *Btree){ 38 if(Btree != NULL){ 39 printf("%d ", Btree -> data); 40 PreOrder(Btree -> lchild); 41 PreOrder(Btree -> rchild); 42 } 43 } 44 void InOrder(Binary *Btree){ 45 if(Btree != NULL){ 46 InOrder(Btree -> lchild); 47 printf("%d ", Btree -> data); 48 InOrder(Btree -> rchild); 49 } 50 } 51 void PostOrder(Binary *Btree){ 52 if(Btree != NULL){ 53 PostOrder(Btree -> lchild); 54 PostOrder(Btree -> rchild); 55 printf("%d ", Btree -> data); 56 } 57 } 58 void LevelOrder(Binary *Btree){ 59 Binary *queue[maxn], *tree; 60 int front = 0, rear = 1; 61 queue[0] = Btree; 62 while(front != rear){ 63 tree = queue[front++]; 64 printf("%d ", tree -> data); 65 if(tree -> lchild != NULL){ 66 queue[rear++] = tree -> lchild; 67 } 68 if(tree -> rchild != NULL){ 69 queue[rear++] = tree -> rchild; 70 } 71 } 72 } 73 int main(){ 74 Binary *Btree = new Binary; 75 Btree = build(Btree); 76 printf(" PreOrder : -> "); 77 PreOrder(Btree); 78 printf(" InOrder : -> "); 79 InOrder(Btree); 80 printf(" PostOrder : -> "); 81 PostOrder(Btree); 82 printf(" LevelOrder : -> "); 83 LevelOrder(Btree); 84 printf(" "); 85 return 0; 86 }
只有不断学习才能进步!