二叉树的操作 深度广度遍历,二叉树递归和非递归遍历

二叉树的操作

参考:[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 q;
	BiNode * p = NULL;
	if(*t)q.push(*t);
	else return;
	
	while(!q.empty())
	{
		p = q.front();
		q.pop();
		cout<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");
}


posted @ 2012-03-29 21:15  foreverlearn  阅读(235)  评论(0编辑  收藏  举报