树的基本操作的算法

#include<iostream>
#define maxsize 100
void visit(BTtree T)
{
	printf("%d",T->data);
}
typedef struct BTNode
{
    int data;    //为简单起见,不妨假设树节点的元素为int型
    struct BTNode *lchild;
    struct BTNode *rchild;
}BTNode,*BTtree;

递归遍历

先序遍历

//递归先序遍历
void PreOrder(BTtree T)
{
	if(T!=NULL)
	{
		visit(T);
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}

中序遍历

//递归中序遍历
void InOrder(BTtree T)
{
	if(T!=NULL)
	{
		InOrder(T->lchild);
		visit(T);
		InOrder(T->rchild);
	}
}

后序遍历

//递归后序遍历
void PostOrder(BTtree T)
{
	if(T!=NULL)
	{
		PostOrder(T->lchild);
		PostOrder(T->rchild);
		visit(T);
	}
}

非递归遍历

先序遍历

//先序非递归
//1.根节点入栈
//2.栈不空,出栈。栈空,结束。
//3.判断出栈结点是否有孩子,右孩子先入栈,左孩子后入栈。跳到第2步。
void PreOrder2(BTtree bt)
{
	if(bt!=NULL)
	{
		BTtree Stack[maxsize];
		int top=-1;
		BTtree p;
		Stack[++top]=bt;
		while(top!=-1)
		{
			p=Stack[top--];//出栈,P为栈顶结点
			visit(p);
			if(p->rchild!=NULL)
				Stack[++top]=p->rchild;
			if(p->lchild!=NULL)
				Stack[++top]=p->lchild;
		}
	}
}

中序遍历

//中序非递归
//1.沿着根的左孩子,依次入栈,直到左孩子为空
//2.出栈,访问栈顶元素,其右孩子为空则重复执行2,若右孩子存在,转向1.

void InOrder2(BTtree T)
{
	if(T!=NULL)
	{
		BTtree Stack[maxsize];
		int top=-1;
		BTtree p=T;//工作结点
		while(top!=-1||p!=NULL)//栈不空或p不空时循环
		{
            if(p!=NULL)
			{
				Stack[++top]=p;
				p=p->lchild;
			}
			else
			{                     //出栈,访问栈顶结点,并转向右子树
				p=Stack[top--];
				visit(p);
				p=p->rchild;     //p指向右孩子,继续循环
			}
		}
	}
}

后序遍历

后续遍历,先将左子树入栈,直到左子树为空,转向右子树,右子树不为空,则以右子树为根又找左子树,否则出栈。当右子树被访问过时也出栈。实际上一个元素会处在栈顶两次,一次是它的右孩子被访问前,一次是右孩子出栈后又回到他这里。所以一个元素如果第二次弹出来,那就将他打印。为了方便,我们可以所有的栈顶结点都先出栈弹出一次,再入栈,再判断它的右孩子。没有右孩子的结点也会被弹出一次,然后马上弹出第二次,并打印。

typedef struct node
{
	int key;
	struct node *left,*right;
	int flag; //标记是否访问过。初始设0
}*Tree,tree;
void PostOrder(Tree root)
{
	Tree p=root;
	Tree stack[maxsize];
	int top=-1;
	while(p!=NULL)
	{
		stack[++top]=p;   //沿着根的左孩子,依次入栈
		p=p->left;
	}
	while(top!=-1)
	{
		p=stack[top--];
		if(p->flag==1)//第二次出栈的结点直接打印
		{
			printf("%d\n",p->key);
		}
		else
		{
			p->flag=1;
			stack[++top]=p;
			p=p->right;//转向右子树
			while(p!=NULL)  
			{
				stack[++top]=p;
				p=p->left;  //找右子树中的左子树
			}
		}
	}
}

还有一种思路就是,因为后序遍历是左右根,那么可以求其逆序,先用类似于先序遍历的思路求根右左,然后依次保存在另一个栈,出栈顺序就是后序遍历的顺序了,即左右根。

//后序遍历非递归
//逆后续遍历等于先序遍历过程中交换左右子树遍历顺序得到的结果,即根右左。
//最后在从后往前地输出逆后续的结果就是后续遍历序列。用两个栈。一个栈前序遍历,一个栈存逆后续序列。
void PostOrder2(BTtree T)
{
	if(T!=NULL)
	{
		BTtree Stack1[maxsize];
		int top1=-1;
		BTtree Stack2[maxsize];
		int top2=-1;
		BTtree p;
		Stack1[++top1]=T; //根节点入栈
		while(top1!=-1)
		{
			p=Stack1[top1--];//出栈
			Stack2[++top2]=p;//出栈结点入栈到stack2
			if(p->lchild!=NULL) //先入左后右,因为先遍历右再遍历左(根右左)
				Stack1[++top1]=p->lchild;
			if(p->rchild!=NULL)
				Stack1[++top1]=p->rchild;

		}
		while(top2!=-1)
		{
			//出栈序列即为后序遍历序列
			p=Stack2[top2--];
			visit(p);
		}
	}
}

层次遍历

//层次遍历
//借助队列来实现
//首先,根节点入队;然后出队,访问出队结点;如果它有左子树,则左子树根节点入队;如果它有右子树,则右子树根结点入队;然后出队,对出队结点访问;循环直到队列为空。
void LevelOrder(BTtree T)
{
	int front,rear;
	BTtree queue[maxsize];
	front=rear=0;
	BTtree q;
	if(T!=NULL)
	{
		queue[rear++]=T;//根结点入队
		while(front!=rear)//队列不为空
		{
			q=queue[front++];//出队
			visit(q);
			if(q->lchild!=NULL)
			{
				queue[rear++]=q->lchild;//左孩子入队
			}
			if(q->rchild!=NULL)
			{
				queue[rear++]=q->rchild;//右孩子入队
			}
		}
	}
}

线索二叉树

//中序线索二叉树中序线索化
//设一个pre,p指针,pre为p的遍历前驱结点,p的左线索如果在,则指向pre,pre的右线索在,则指向p。
void InThread(BTtree p,BTtree pre)
{
	if(p!=NULL)
	{
		InThread(p->lchild,pre);//左子树线索化
		if(p->lchild==NULL)
		{
			p->lchild=pre;
			p->ltag=1;
		}
		if(pre!=NULL&&pre->rchild==NULL)
		{
			pre->rchild=p;
			pre->rtag=1;
		}
		pre=p;
		p=p->rchild;
		InThread(p,pre);//右子树线索化
	}
}
void createInThread(BTtree root)
{
	BTtree pre=NULL;
	if(root!=NULL)
	{
		InThread(root,pre);
		pre->rchild=NULL;
		pre->rtag=1;
	}
}

二叉排序树

递归查找

//二叉排序树的递归查找
BTtree Search(BTtree bt,int key)
{
	if(bt==NULL)
	{
		return NULL;
	}
	else
	{
		if(bt->data==key)
			return bt;
		else if(key<bt->data) //小于根节点关键字就到左子树中去找
			return Search(bt->lchild,key);
		else 
			return Search(bt->rchild,key);
	}
}

非递归查找

//二叉排序树的非递归查找
BTtree Search2(BTtree T,int key)
{
	while(T!=NULL&&key!=T->data)
	{
		if(key<T->data)T=T->lchild;
		else
			T=T->rchild;
	}
	return T;
}

插入

//二叉排序树的插入
int Insert(BTtree &T,int k)
{
	if(T==NULL)  //原树为空,新插入的记录为根结点
	{
		T=(BTNode*)malloc(sizeof(BTNode));
		T->data=k;
		T->lchild=T->rchild=NULL;
		return 1;
	}
	else if(k==T->data)
		return 0;
	else if(k<T->data)
		return Insert(T->lchild,k);
	else
		return Insert(T->rchild,k);
}

构造

//二叉树的构造
void Creat(BTtree &T,int str[],int n)
{
	T=NULL;
	int i=0;
	while(i<n)
	{
		Insert(T,str[i]);
		i++;
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值