二叉树的递归和非递归实现前序、中序、后序、层次遍历

二叉树的遍历方式一般有前序、中序、后序三种方式。其中每种方式都可以由递归和非递归实现,非递归主要借助于栈来实现,还可以借助队列实现层级遍历。下面的代码在vs2019编译通过,其中的栈和队列是自己简单实现的。实现思路和代码如下:

#include 
#define  _CRT_SECURE_NO_WARNINGS
#define  STACK_SIZE 100
#define  QUEUE_SIZE 100


typedef struct Btree {
	char data;
	struct Btree* lChild;
	struct Btree* rChild;
}Btree, *PBtree;

//循环队列
class Myqueue
{
private:
	PBtree queue[QUEUE_SIZE];
	int front, rear;

public:
	Myqueue()
	{
		rear = front = 0;
	}

	bool IsEmpty()
	{
		return rear == front ? true : false;
	}

	bool enQueue(const PBtree T)
	{
		if ((rear + 1) % QUEUE_SIZE == front) 
		{
			return false;
		}
		queue[rear] = T;
		rear = (rear + 1) % QUEUE_SIZE;
		return true;
	}

	PBtree deQueue()
	{
		if ( rear == front)
		{
			return NULL;
		}
		PBtree p = queue[front];
		front = (front + 1) % QUEUE_SIZE;	
		return p;
	}

};

//栈
class MyStack
{
private:
	PBtree stack[STACK_SIZE];
	int top;
public:
	MyStack()
	{
		top = -1;
	}

	bool IsEmpty()
	{
		return -1 == top ? true : false;
	}

	bool push(const PBtree T)
	{
		if (STACK_SIZE - 1 == top )
		{
			return false;
		}
		stack[++top] = T;
		return true;
	}

	PBtree pop()
	{
		if (-1 == top)
		{
			return NULL;				 
		}
		return stack[top--];
	}

};


//采用前序创建二叉树
void CreateTree(PBtree *T)
{
    char data;
	scanf_s("%c", &data);
	if (data == '#')
	{
		*T = NULL;
		return;
	}
	else
	{
		*T = (PBtree)malloc(sizeof(Btree));
		if (!*T)
		{
			exit(-1);
		}
		(*T)->data = data;
		CreateTree(&(*T)->lChild);
		CreateTree(&(*T)->rChild);
	}
}

//递归前序遍历 
//比较简单 按照根-左-右顺序访问即可
void PreOrder(PBtree T)
{
	if (T)
	{
		printf("--%c--", T->data);
		PreOrder(T->lChild);
		PreOrder(T->rChild);
	}
}

//非递归前序遍历
//思路:初始将根节点入栈,栈不空就继续循环,出栈访问栈顶元素(根结点),再看右子树
//不空入栈,再看左子树,不空入栈(根据栈先入后出的特点)
void PreOrderNoRecursion(const PBtree T)
{
	if (!T) return;
	MyStack stack;
	PBtree p = T;
	stack.push(p);
	while (!stack.IsEmpty())
	{
		p = stack.pop();
		printf("--%c--", p->data);
		if (p->rChild)
		{
			stack.push(p->rChild);
		}
		if (p->lChild)
		{
			stack.push(p->lChild);
		}
	}

}

//递归中序遍历
//左-根-右
void InOrder(PBtree T)
{
	if(T)
	{
		InOrder(T->lChild);
		printf("--%c--", T->data);
		InOrder(T->rChild);
	}
}


//非递归中序遍历
//思路:左子树入栈遍历到最左边,栈不空,则退栈访问栈顶元素(根结点),再将右子树入栈
//继续循环,注意循环条件为栈不空或者指针不空
void InOrderNoRecursion(const PBtree T)
{
	MyStack stack;
	PBtree p = T;

	while (!stack.IsEmpty() || p != NULL)
	{
		while(p) //if(p) 
		{
			stack.push(p);
			p = p->lChild;
		}
		if(!stack.IsEmpty())//else  
		{
			p = stack.pop();//
            printf("--%c--", p->data);
			p = p->rChild;
		}			
	}
}

//递归后序遍历
//左-右-根
void PostOrder(PBtree T)
{
	if (T)
	{
		PostOrder(T->lChild);
		PostOrder(T->rChild);
		printf("--%c--", T->data);
	}
}

//非递归后序遍历(方法较多,这里选取最容易理解的一种)
//非递归后序遍历和非递归前序遍历存在联系,仔细观察可以得到如下规律:
//1栈:调整前序非递归遍历的入栈顺序为  先左后右
//2栈:将前序遍历的访问操作存入2栈,然后输出2栈即可
void PostOrderNoRecursion(const PBtree T)
{
	if (!T) return;
	MyStack stack1;
	MyStack stack2;
	
	PBtree p = T;
	stack1.push(p);

	while (!stack1.IsEmpty())
	{
		p = stack1.pop();
		stack2.push(p);

		if (p->lChild)
		{
			stack1.push(p->lChild);
		}
		if (p->rChild)
		{
			stack1.push(p->rChild);
		}
	}
	
	while (!stack2.IsEmpty())
	{
		p = stack2.pop();
		printf("--%c--", p->data);
	}

}


//层次遍历,借助队列实现
//根先入队,出队访问,并按照从左到右依次将子树入队即可,队空退出循环
void LevelOrder(const PBtree T)
{
	Myqueue queue;
	PBtree p = T;
	queue.enQueue(p);
	while (!queue.IsEmpty())
	{
		p = queue.deQueue();
		printf("--%c--", p->data);
		if (p->lChild)
		{
			queue.enQueue(p->lChild);
		}
		if (p->rChild)
		{
			queue.enQueue(p->rChild);
		}
	}
}


int main()
{
	printf("please input string in PreOrder(# is null)!\n");
	//abc##d##e#f##
    /*            a
	            /   \
        	   b     e
 	          / \     \
	         c   d     f                   
    */

	PBtree T;
	CreateTree(&T);

	printf("\n PreOrder-Recursion:\n");
	PreOrder(T);
    printf("\n PreOrder-No-Recursion:\n");
	PreOrderNoRecursion(T);
	
	printf("\n InOrder-Recursion:\n");
	InOrder(T);
	printf("\n InOrder-No-Recursion:\n");
	InOrderNoRecursion(T);

	printf("\n PostOrder-Recursion:\n");
	PostOrder(T);
	printf("\n PostOrder-No-Recursion:\n");
	PostOrderNoRecursion(T);

	printf("\n LevelOrder:\n");
	LevelOrder(T);

	return 0;
}


你可能感兴趣的:(数据结构与算法,系统架构)