现在的位置: 首页 > 综合 > 正文

二叉树按层次遍历–队列实现

2013年04月06日 ⁄ 综合 ⁄ 共 3080字 ⁄ 字号 评论关闭

    最近数据结构看的还真是恶心额,脑子不好使,算法写不来额大哭·····

    二叉树一大堆概念性的东西,不过还是写吧。


二叉树(binary tree)

二叉树的基本形态
  二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:
  (1)空二叉树——(a);  
      (2)只有一个根结点的二叉树——(b);
  (3)只有左子树——(c);
  (4)只有右子树——(d);
  (5)完全二叉树——(e)

度(Degree):节点孩子的数目。
叶子(Leaf): 度为0的节点称为叶子。
深度(Depth):树中最大的层次(从最上0开始数)

满二叉树:一棵深度为k且有2^k -1个节点的二叉树。
完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶子节点,并且叶子节点都是从左到右依次排布,这就是完全二叉树。

性质1:在二叉树的第i层上至多有2^(i-1)个节点(i >= 1)
性质2:深度为k的二叉树至多有2^k - 1个节点
性质3:任意一棵二叉树T,若其叶子节点数为n0,度为2的节点数为n2,则n0 = n2 + 1

对于完全二叉树:

性质4:具有n个节点的完全二叉树的深度是[log2n] + 1
性质5:有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
    若I为结点编号则 如果I<>1,则其父结点的编号为I/2;
    如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
    如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。


二叉树按层次遍历----队列实现
1.创建二叉树,输入#代表NULL,调用递归创建二叉树。
2.构建一个队列专门用来储存二叉树节点指针,先把根节点入队,假设是A,对A元素进行访问,然后对A的左右孩子依次入队,假设B,C。A出队列,再是对B进行访问,同样将B的左右孩子入队列,B出对列······重复以上,知道队列为空。

下面是的代码是实现按层次从上到下遍历二叉树:

#include <Windows.h>
#include <stdio.h>

#define ElemType char 

typedef struct TreeNode{				//单位节点
	struct TreeNode *LChild;
	struct TreeNode *RChild;
	ElemType c;
}TreeNode,* p_Tree;

typedef struct Link{					//单向链表
	struct Link *Next;
	TreeNode *Node;
}Link,*P_Link;

typedef struct Queue{					//形成队列
	P_Link front;						
	P_Link rear;
	int Q_Len;
}Queue,*p_Queue;

BOOL PrintElement(ElemType e);			//对二叉树节点的操作,自定义,这里我设置为打印出内容
BOOL CreateTree(p_Tree* pBiTree);		//创建二叉树
P_Link InitLink(P_Link L);				//初始化链表				
P_Link InsertLink(P_Link L,TreeNode *Tree_Node,p_Queue *Q);				//插入队列
p_Queue GetTopLinkNode(P_Link L, BOOL(*Visit)(ElemType),p_Queue Q);		//取出队列第一个元素,并且访问左右孩子
p_Queue InitQueue(p_Queue T,P_Link L);									//初始化队列

int main() 
{
	p_Tree Tree = NULL;			
	P_Link Link = NULL;
	p_Queue Queue = NULL;
	if(!CreateTree(&Tree))												//创建二叉树
	{
		printf("Create Tree Error\n");
		return 0;
	}
	p_Tree p_Temp_Node = Tree;
	Link = InitLink(Link);	
	Queue = InitQueue(Queue,Link);
	
	Link = InsertLink(Link,p_Temp_Node,&Queue);						 //根节点入队

	BOOL(*Operate)(ElemType);										//定义函数指针
	Operate = PrintElement;

	while(Queue->front != Queue->rear)
	{			
		Queue = GetTopLinkNode(Link,Operate,Queue);					//获取队列第一个节点
	    Link = InsertLink(Link,Queue->front->Node->LChild,&Queue);	//左孩子入队
		Link = InsertLink(Link,Queue->front->Node->RChild,&Queue);	//右孩子入队
	}

	return 0;
}

BOOL CreateTree(p_Tree* pBiTree)
{
	ElemType ch;
	ch = getchar();
	if (ch == '#')													//#代表NULL
	{
		(*pBiTree) = NULL;
	}
	else
	{
		(*pBiTree) = (p_Tree)calloc(1,sizeof(TreeNode));
		if (!(*pBiTree))
		{
			printf("Allocate Memory Error\n");
			return FALSE;
		}
		else
		{
			(*pBiTree)->c = ch;
			CreateTree(&(*pBiTree)->LChild);			//调用递归创建二叉树
			CreateTree(&(*pBiTree)->RChild);
		}
	}
		return TRUE;
}

P_Link InitLink(P_Link L)
{
	L = (P_Link)calloc(1,sizeof(Link));
	if (!L)
	{
		printf("Memory Error\n");
		return NULL;
	}
	L->Node = NULL;
	L->Next = NULL;
	return L;
}

p_Queue InitQueue(p_Queue T,P_Link L)
{
	T = (p_Queue)calloc(1,sizeof(Queue));
	T->Q_Len = 0;
	T->front = L;
	T->rear = L;
	return T;
}

P_Link InsertLink(P_Link L,TreeNode *Tree_Node,p_Queue *Q)
{
	if (Tree_Node == NULL)
	{	
		return L;
	}
	else
	{
		static P_Link p = L;
		P_Link pNew;
		pNew = (P_Link)calloc(1,sizeof(Link));
		if (!pNew)
		{
			printf("Memory Error\n");
			return 0;
		}	
		pNew->Node = Tree_Node;		//New Node
		pNew->Next = NULL;
		p->Next = pNew;				//p to Next
		p = pNew;
		(*Q)->rear = p;			   //Add Queue
		(*Q)->Q_Len++ ;			   //Q len ++
		return L;
	}
}

p_Queue GetTopLinkNode(P_Link L, BOOL(*Visit)(ElemType),p_Queue Q)
{
	Q->front = Q->front->Next;    //remove first Node
	Visit(Q->front->Node->c);
	Q->Q_Len--;
	return Q;
}

BOOL PrintElement(ElemType e)
{
	// 输出元素e的值
	printf("%c",e);
	return TRUE;
}

抱歉!评论已关闭.