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

原创 2012年03月29日 21:15:23

二叉树的操作

参考:[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");
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

二叉树的非递归遍历及算法分析

用递归遍历的优点是算法简单明了,缺点也十分明显:对于栈的消耗比较大。尤其是在嵌入式应用中,嵌入式处理器资源往往有限。每次递归调用,都会涉及到通用寄存器、SP指针、PC指针等的压栈。当树的深度比较大时,...
  • u012914709
  • u012914709
  • 2015年03月20日 22:29
  • 696

二叉树的递归和非递归方式的三种遍历

二叉树的三种遍历方式,前序遍历,中序遍历,后序遍历,中的前中后都是指的是根节点的访问顺序,这三种遍历方式的概念在这里就不多说了,太普遍了! 二叉树的建立 我们这里以前序遍历为例: 我们先定...
  • woshinannan741
  • woshinannan741
  • 2016年10月16日 13:18
  • 800

详细讲解二叉树三种遍历方式的递归与非递归实现

详细讲解二叉树三种遍历方式的递归与非递归实现 分类: 数据结构随笔2013-10-24 08:58 518人阅读 评论(14) 收藏 举报 二叉树是一种非常重要的数据结...
  • pi9nc
  • pi9nc
  • 2013年10月24日 23:44
  • 44666

二叉树的建立、三种(递归、非递归)遍历方法

二叉树定义: 1.有且仅有一个特定的称之为根root的结点 2.当n>1时,除根结点之外的其余结点分为两个互不相交的子集。他们称为二叉树的左子树和右子树。 二叉树的一种建立方法: 若对有n个结...
  • jiang111_111shan
  • jiang111_111shan
  • 2015年06月08日 21:42
  • 1000

C语言实现二叉树的递归遍历与非递归遍历

本文实现了对二叉树的递归遍历和非递归遍历,当然还包括了一些栈操作。           二叉树的遍历本质上其实就是入栈出栈的问题,递归算法简单且容易理解,但是效率始终是个问题。非递归算法可以清楚的知道...
  • B_boyi
  • B_boyi
  • 2016年05月14日 10:35
  • 548

C++实现——二叉树的四种遍历(非递归写法)

#include #include #include #include using namespace std;//结构体定义如下 typedef struct TreeNode{ //...
  • langmanqishizaijia
  • langmanqishizaijia
  • 2016年04月09日 19:27
  • 2379

java使用递归,非递归方式实现二叉树的三种常见遍历方式

二叉树的定义: 二叉树(binary tree)是结点的有限集合,这个集合或者空,或者由一个根及两个互不相交的称为这个根的左子树或右子树构成. 从定义可以看出,二叉树包括:1.空树 2.只有一...
  • lr131425
  • lr131425
  • 2017年03月07日 10:48
  • 2524

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

二叉树的操作 参考:[1]http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html     [2]http://...
  • lishenglong666
  • lishenglong666
  • 2016年05月29日 21:45
  • 444

二叉树的非递归遍历(不用栈、O(1)空间)

本文主要解决一个问题,如何实现二叉树的前中后序遍历,有两个要求: O(1)空间复杂度,即只能使用常数空间; 二叉树的形状不能被破坏(中间过程允许改变其形状)。 通常,实现二叉树的前序(preorder...
  • cyuyanenen
  • cyuyanenen
  • 2016年06月09日 14:23
  • 2674

二叉树的实现(递归遍历和非递归遍历)C++

二叉树的操作,使用栈构建一棵二叉树,然后求树高,递归先序遍历,中序遍历,后序遍历,访问左节点,访问右节点,非递归先序遍历输出,非递归中序遍历输出,非递归后序遍历输出。...
  • J_Anson
  • J_Anson
  • 2015年11月06日 00:32
  • 3547
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉树的操作 深度广度遍历,二叉树递归和非递归遍历
举报原因:
原因补充:

(最多只允许输入30个字)