二叉树
使用链式存储
。
因为书上的大题使用的都是链式存储
。所以我也采取这样的方式,作为我的算法模板。
二叉树的类型描述
1 2 3 4
| typedef struct BiTNode{ int data; struct BiTNode * lchild, * rchild; }BiTNode, * BiTree;
|
先序递归建树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| BiTree CreateBiTree(){ BiTNode * root = (BiTNode *)malloc(sizeof(BiTNode)); int ch; cin >> ch; if(ch == -1){ root = NULL; }else{ root -> data = ch; root -> lchild = CreateBiTree(); root -> rchild = CreateBiTree(); } return root; }
|
先序遍历
1 2 3 4 5 6 7 8
| void PreOrder(BiTree root){ if(root){ cout << root -> data << endl; PreOrder(root -> lchild); PreOrder(root -> rchild); } }
|
中序遍历
1 2 3 4 5 6 7 8
| void InOrder(BiTree root){ if(root){ InOrder(root -> lchild); cout << root -> data << endl; InOrder(root -> rchild); } }
|
后序遍历
1 2 3 4 5 6 7 8
| void PostOrder(BiTree root){ if(root){ PostOrder(root -> lchild); PostOrder(root -> rchild); cout << root -> data << endl; } }
|
先序遍历的非递归算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void PreOrder2(BiTree root){ SqStack s; InitStack(s); BiTNode * p = root; while(p || !EmptyStack(s)){ if(p){ cout << p -> data << endl; Push(s, p); p = p -> lchild; }else{ Pop(s, p); p = p -> rchild; } } }
|
关于先序遍历的非递归算法:
根左右
,先根的性质,决定了在一路向左
的过程,是可以边输出边入栈
的。- 模拟递归回溯,也就是
else
部分,此时已经完成了根左
。现就只要出栈,并转向出栈结点的右子树。
中序遍历的非递归算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void InOrder2(BiTree root){ SqStack s; InitStack(s); BiTNode * p = root; while(p || !EmptyStack(s)){ if(p){ Push(s, p); p = p -> lchild; }else{ Pop(s, p); cout << p -> data << endl; p = p -> rchild; } } }
|
关于中序遍历的非递归算法:
- 与
先序遍历的非递归算法
类似,不同的是什么时候访问结点
。 左根右
,决定了必须要找到最左边的结点再回溯。else
部分,也就是模拟递归回溯过程,必须要先出栈
再拿着那个结点的值访问。
后序遍历非递归算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| void PostOrder2(BiTree root){ SqStack s; InitStack(s); BiTNode * p = root; BiTNode * r = NULL; while(p || !EmptyStack(s)){ if(p){ Push(s, p); p = p -> lchild; }else{ GetTop(s, p); if(p -> rchild && p -> rchild != r){ p = p -> rchild; }else{ Pop(s, p); cout << p -> data << endl; r = p; p = NULL; } } } }
|
关于后序遍历的非递归算法:
- 指针
r
:回溯的过程中,可能是从左边回溯,也可能是从右边回溯。∴
从左边回溯,那么根结点就没被访问过。从右边回溯,那么根结点被访问过。根结点被访问过,说明该直接从栈顶弹出一个元素。
层序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void LevelOrder(BiTree root){ SqQueue q; InitQueue(q); EnQueue(q, root); while(!EmptyQueue(q)){ BiTNode * t; DeQueue(q, t); cout << t -> data << endl; if(t -> lchild) EnQueue(q, t -> lchild); if(t -> rchild) EnQueue(q, t -> rchild); } }
|