二叉树的操作
参考:[1]http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
[2]http://www.bccn.net/article/kfyy/sjjg/200706/4585.html
- #include"stdio.h"
- #include<iostream>
- #include<stack>
- using namespace std;
- //数据结构
- typedef struct node
- {
- int value;
- struct node *lchild;
- struct node *rchild;
- }BiNode;
- typedef BiNode* BiTree;
- typedef struct BTNode{
- BiNode * btnode;
- bool isFrist;
- }BTNode;
- //初始化
- void InitBiTree(BiTree *T)
- {
- *T = NULL;
- }
- //创建
- void CreateBiTree(BiTree *T)
- {
- int value;
- printf("输入值:\n");
- scanf("%d",&value);
- if(value!= 0)
- {
- *T = (BiNode *)malloc(sizeof(BiNode));
- (*T)->value = value;
- (*T)->lchild = NULL;
- (*T)->rchild = NULL;
- CreateBiTree(&((*T)->lchild));
- CreateBiTree(&((*T)->rchild));
- }
- else
- {
- *T = NULL;
- return;
- }
- }
- //按层创建
- void CreateBiTreeByLevel(BiTree *T,int *Array,int i,int len)
- {
- if((Array[i] == 0)|| i > len)return;
- *T = (BiNode *)malloc(sizeof(BiNode));
- if(!(*T))exit(0);
- (*T) ->value = Array[i];
- (*T)->lchild = NULL;
- (*T)->rchild = NULL;
- CreateBiTreeByLevel(&(*T)->lchild,Array,2*i,len);
- CreateBiTreeByLevel(&(*T)->rchild,Array,2*i+1,len);
- }
- void display(BiTree *t) //显示树形结构
- {
- if(*t!=NULL)
- {
- cout<<(*t)->value;
- if((*t)->lchild!=NULL)
- {
- cout<<'(';
- display(&(*t)->lchild);
- }
- if((*t)->rchild!=NULL)
- {
- cout<<',';
- display(&(*t)->rchild);
- cout<<')';
- }
- }
- }
- //----------------深度遍历二叉树-------递归的方法-------
- //前序遍历
- void PreOrderTraverse(BiTree *t)
- {
- if(!(*t))return;
- printf("%d",(*t)->value);
- PreOrderTraverse(&((*t)->lchild));
- PreOrderTraverse(&((*t)->rchild));
- }
- // 后序遍历
- void PostOrderTraverse(BiTree *t)
- {
- if(!(*t))return;
- PostOrderTraverse(&((*t)->lchild));
- PostOrderTraverse(&((*t)->rchild));
- printf("%d",(*t)->value);
- }
- //中序遍历
- void InOrderTraverse(BiTree *t)
- {
- if(!(*t))return;
- InOrderTraverse(&(*t)->lchild);
- printf("%d",(*t)->value);
- InOrderTraverse(&(*t)->rchild);
- }
- //-------------------深度遍历二叉树---非递归方法---------------------------
- //非递归前序遍历
- /************************************************************************/
- /* 1)访问节点p,将节点p入栈*/
- /* 2)p左孩子不为空,则一直入栈,当p的左孩子为空时,出栈*/
- /* 3)直到p为空或者栈s为空,遍历结束*/
- /*前序遍历根左右,入栈时访问为谦虚,中序遍历时,左根右,出栈时访问*/
- /************************************************************************/
- void PreOrderTraverse1(BiTree *t)
- {
- stack <BiTree> s;
- BiNode *p = *t;
- while(p!=NULL||!s.empty())
- {
- while(p)
- {
- printf("%d",p->value);
- s.push(p);
- p = p->lchild;
- }
- if(!s.empty())
- {
- p = s.top();
- s.pop();
- p = p->rchild;
- }
- }
- }
- //非递归中序遍历
- void InOrderTraverse1(BiTree *t)
- {
- stack<BiTree> s;
- BiNode *p = *t;
- while(p!=NULL || !s.empty())
- {
- while(p)
- {
- s.push(p);
- p = p->lchild;
- }
- if(!s.empty())
- {
- p = s.top();
- printf("%d",p->value);
- s.pop();
- p = p->rchild;
- }
- }
- }
- //后续非递归遍历
- /*
- 第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,
- 此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同
- 的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。
- 这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现
- 在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
- */
- void PostOrderTraverse1(BiTree *t)
- {
- stack<BTNode*> s;
- BiNode *p = *t;
- BTNode *temp;
- while(p!=NULL||!s.empty())
- {
- while(p)
- {
- BTNode *btn = (BTNode *)malloc(sizeof(BTNode));
- btn->btnode = p;
- btn->isFrist = true;
- s.push(btn);
- p = p->lchild;
- }
- if(!s.empty())
- {
- temp = s.top();
- s.pop();
- if(temp->isFrist)
- {
- s.push(temp);
- temp->isFrist = false;
- p = temp->btnode->rchild;
- }
- else
- {
- printf("%d",temp->btnode->value);
- p = NULL;
- }
- }
- }
- }
- /*
- 第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。
- 如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右
- 孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次
- 入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点
- 前面被访问。
- */
- void PostOrderTraverse2(BiTree *t)
- {
- stack<BiNode*> s;
- BiNode *pre = NULL;
- BiNode *cur = NULL;
- s.push(*t);
- while(!s.empty())
- {
- cur = s.top();
- if(((cur->lchild == NULL)&&(cur->rchild == NULL))||(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
- {
- printf("%d",cur->value);//如果当前结点没有孩子结点或者孩子节点都已被访问过
- s.pop(); //由于入栈时根右左,pre指向其右或者左节点,
- pre = cur;
- }
- else
- {
- if(cur->rchild!=NULL)s.push(cur->rchild);
- if(cur->lchild!=NULL)s.push(cur->lchild);
- }
- }
- }
- //----------------------------------广度遍历二叉树----------使用队列按照层序遍历二叉树-----------------------
- void LevelOrderTranverse(BiTree *t)
- {
- queue<binode> q;
- BiNode * p = NULL;
- if(*t)q.push(*t);
- else return;
- while(!q.empty())
- {
- p = q.front();
- q.pop();
- cout<<p->value<<"*";
- if (p->lchild!=NULL)q.push(p->lchild);
- if (p->rchild!=NULL)q.push(p->rchild);
- }
- }
- int main()
- {
- BiTree T;
- InitBiTree(&T);
- int a[14] = {0,1,2,3,4,5,6,0,0,0,7,0,8,9};//从下标1开始,0标识没有节点
- CreateBiTreeByLevel(&T,a,1,13);
- display(&T);
- printf("\n---------PreOrder---------------\n");
- PreOrderTraverse(&T);
- printf("\n--------------------------------\n");
- PreOrderTraverse1(&T);
- printf("\n---------InOrder-----------------\n");
- InOrderTraverse(&T);
- printf("\n------------------------\n");
- InOrderTraverse1(&T);
- printf("\n---------PostOrder---------------\n");
- PostOrderTraverse(&T);
- printf("\n---------------------------------\n");
- PostOrderTraverse1(&T);
- printf("\n---------------------------------\n");
- PostOrderTraverse2(&T);
- system("pause");
- }
- </p-></binode>