二叉树的建立、前中后序、层次遍历

一、预备知识(栈和队列)

这两个作为最基础的数据结构相信大家已经掌握了,但是如果要对二叉树进行操作的话,还是有必要回顾一下队列(先进后出)和栈(先进先出)的基本性质和操作的。

 队列的基础代码

typedef struct LinkNode {
	BiTree data;
	struct LinkNode* next;
}LinkNode;
typedef struct {
	LinkNode* front, * rear;//头指针,尾指针不用现设
}LinkQueue;

void InitQueue(LinkQueue& Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;
}

bool IsEmpty(LinkQueue Q)
{
	if (Q.front == Q.rear)
		return true;
	else return false;
}

void EnQueue(LinkQueue &Q,BiTree x)
{
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	s->data = x;
	s->next = NULL;
	Q.rear->next = s;
	Q.rear = s;
}

bool DeQueue(LinkQueue& Q, BiTree& x)
{
	if(Q.front == Q.rear) return false;
	LinkNode* p = Q.front->next;
	x = p->data;
	Q.front->next = p->next;//删除第二个节点,也就是队头
	if (Q.rear == p)
		Q.rear = Q.front;
	free(p);
	return true;
}

 

栈的基础代码 

typedef struct {
	BiTree data[MaxSize];
	int top;
}SqStack;

void InitStack(SqStack &S) {
	S.top = -1;
}

bool StackEmpty(SqStack& S) {
	return (S.top == -1) ? true : false;
}

bool Push(SqStack& S, BiTree x)
{
	if (S.top == MaxSize - 1) return false;
	S.data[++S.top] = x;
	return true;
}

bool Pop(SqStack& S, BiTree& x)
{
	if (S.top == -1) return false;
	x = S.data[S.top--];
	return true;
}

bool GetTop(SqStack& S, BiTree& x)
{
	if (S.top == -1) return false;
	x = S.data[S.top]; return true;
}

 

二、二叉树的建立

二叉树的建立可以有很多种方法,下面是用链表建立的方法。就是把数据先存入节点塞进链表里面,再逐层取出节点给他们连成二叉树的样子。

typedef struct BiTNode{
	char c;
	struct BiTNode *lchild;
	struct BiTNode *rchild;
}BiTNode,*BiTree;


typedef struct tag{
	BiTree p;//树的某一个结点的地址值
	struct tag *pnext;
}tag_t,*ptag_t;


int main()
{
	BiTree pnew;
	int i,j,pos;
	char c;
	BiTree tree=NULL;//树根
	ptag_t phead=NULL,ptail=NULL,listpnew,pcur;//phead就是队列头,ptail就是队列尾
	
	while(scanf("%c",&c)!=EOF)
	{
		if(c=='\n')
		{
			break;
		}
		pnew=(BiTree)calloc(1,sizeof(BiTNode));
		pnew->c=c;//数据放进去
		listpnew=(ptag_t)calloc(1,sizeof(tag_t));//给队列结点申请空间
		listpnew->p=pnew;
		if(NULL==tree)
		{
			tree=pnew;//树的根
			phead=listpnew;//队列头
			ptail=listpnew;//队列尾
			pcur=listpnew;
			continue;
		}else{                            
			ptail->pnext=listpnew;//新结点放入链表,通过尾插法
			ptail=listpnew;//ptail指向队列尾部
		}//pcur始终指向要插入的结点的位置
		if(NULL==pcur->p->lchild)//如何把新结点放入树
		{
			pcur->p->lchild=pnew;//把新结点放到要插入结点的左边
		}else if(NULL==pcur->p->rchild)
		{
			pcur->p->rchild=pnew;//把新结点放到要插入结点的右边
			pcur=pcur->pnext;//左右都放了结点后,pcur指向队列的下一个
		}
	}
	printf("--------前序遍历----------\n");
	preOrder(tree);
	printf("\n--------中序遍历------------\n");
	InOrder(tree);
	printf("\n--------后序遍历------------\n");
	PostOrder(tree);
	printf("\n--------前序非递归遍历----------\n");
	PreOrder2(tree);
	printf("\n--------中序遍历非递归------\n");
	InOrder2(tree); 
	printf("\n--------层次遍历-----------\n");
	LevelOrder(tree);
	printf("\n");
	system("pause");
} 

三、前中后序遍历

前序遍历,首先访问父节点,然后是左孩子和右孩子。非递归方法就是从左到右,从上到下溜达,把路过的节点访问完存到栈里面,然后在没有子节点的时候就出栈。

中序遍历的原理和上面差不多,唯一的区别是他是出栈后访问,就不再赘述了。 

void preOrder(BiTree p)
{
	if(p!=NULL)
	{
		putchar(p->c);//等价于visit函数
		preOrder(p->lchild);
		preOrder(p->rchild);
	}
}
//中序遍历  hdibjeafcg
void InOrder(BiTree p)
{
	if(p!=NULL)
	{
		InOrder(p->lchild);
		putchar(p->c);
		InOrder(p->rchild);
	}
}
//hidjebfgca
void PostOrder(BiTree p)
{
	if(p!=NULL)
	{
		PostOrder(p->lchild);
		PostOrder(p->rchild);
		putchar(p->c);
	}
}
//中序遍历非递归,非递归执行效率更高,考的概率很低
void InOrder2(BiTree T)
{
	SqStack S;
	InitStack(S);BiTree p=T;
	while(p||!StackEmpty(S))//逻辑或||
	{
		if(p)
		{
			Push(S,p);
			p=p->lchild;
		}else{
			Pop(S,p);putchar(p->c);
			p=p->rchild;
		}
	}
}

void PreOrder2(BiTree T)
{
	SqStack S;
	InitStack(S);BiTree p = T;
	while (p || !StackEmpty(S))	{
		if (p)
		{
			putchar(p->c);
			Push(S, p);
			p = p->lchild;
		
		}
		else {
			Pop(S, p);
			p = p->rchild;
		}
	}
}

四、层序遍历

根节点入队。然后出队并且检查他们是否有孩子,如果有就按照左孩子右孩子的顺序,依次入队。 然后循环往复,直到队列里面一个节点都没有。

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA54Of5Zux6YeM6aOY5Ye655qE5LqR6aqo5py15YS_,size_4,color_FFFFFF,t_70,g_se,x_16

就拿上图来说,队列里的情况为:A-->(A)BC-->(A)(B)(C)DEFG-->(A)(B)(C)(DE)(FG)。其中括号内是被删除的节点。A的出队的同时BC入队,然后你就会发现每一次访问到下一层节点时队列里面就正好是这个层节点的顺序。

void LevelOrder(BiTree T)
{
	LinkQueue Q;
	InitQueue(Q);
	BiTree p;
	EnQueue(Q,T);//树根入队
	while(!IsEmpty(Q))
	{
		DeQueue(Q,p);
		putchar(p->c);
		if(p->lchild!=NULL)
			EnQueue(Q,p->lchild);
		if(p->rchild!=NULL)
			EnQueue(Q,p->rchild);
	}
}

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值