数据结构实验三(二叉树)

题目描述建立二叉树并采用先序、中序、后序遍历二叉树。
本次创建二叉树的方法采用 AB…C…的方法(A为根结点,B为左节点,C为右节点,B,C均为孩子节点)
  递归分析:理解二叉树,要从本质入手,最本质的思想就是递归。传入函数根结点,每一个孩子节点其实就是下一个孩子节点的父亲节点,就相当于根节点。很明显与递归思想类似,将问题拆分为小问题,从小问题入手。
  非递归分析,在数据结构前面,我们可以使用栈来消除递归,这是因为递归本质思想还是先进后出。本次一一分析先中后序的非递归方法,但仅提供后序(因为最难)
实验二的代码已全部公开,可进行查看。链接:https://blog.csdn.net/QAZJOU/article/details/120790581
当然为简化程序,本次使用C++STLstack模版,注意是指针类型。
先序:对于任一结点P:
1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;3)直到P为NULL并且栈为空,则遍历结束。

中序类似先序,只要改变visit函数位置就行。
下面重点谈谈后序。

要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
全部代码C++,C(只有非递归版)
BiTreeRC.h递归头文件

#pragma once
#ifndef BITREERC_H
#define BITREEC_H


#include <iostream>
#include <malloc.h>
using namespace std;

typedef struct Bitree {
	char data;
	struct Bitree* Lchild;
	struct Bitree* Rchild;
}Bitree,*Bit;

//创建二叉树
void CreatBit(Bit* root) {
	char ch;
	ch = getchar();
	if (ch == '.') *root = NULL;
	else {
		*root = (Bitree*)malloc(sizeof(Bitree));
		(*root)->data = ch;
		CreatBit(&((*root)->Lchild));
		CreatBit(&((*root)->Rchild));
	}
}

void visit(char ch) {
	cout << ch<<" ";
}

//先序遍历
void Preorder(Bit root) {
	if (root != NULL) {
		visit(root->data);
		Preorder(root->Lchild);
		Preorder(root->Rchild);
	}
}

void Inorder(Bit root) {
	if (root != NULL) {
		Inorder(root->Lchild);
		visit(root->data);
		Inorder(root->Rchild);
	}
}

void Postorder(Bit root) {
	if (root != NULL) {
		Postorder(root->Lchild);
		Postorder(root->Rchild);
		visit(root->data);
	}
}

#endif // !BITREERC_H

BiTreeNRC.h非递归头文件

#pragma once
#ifndef BITREENRC_H
#define BITREENRC_H

#include "BiTreeRC.h"
#include <stack>

void nInorder(Bit root) {
	stack<Bit> v;//建立栈,注意类型
	Bit p;
	p = root;
	while (p != NULL || !v.empty()) {
		while (p != NULL) {
			v.push(p);
			p = p->Lchild;
		}
		if(!v.empty()) {
			p = v.top();
			visit(p->data);
			v.pop();
			p = p->Rchild;
		}
	}
}

//先序
void nPreorder(Bit root) {
	stack<Bit> v;//建立栈,注意类型
	Bit p;
	p = root;
	while (p != NULL || !v.empty()) {
		while(p != NULL) {
			visit(p->data);
			v.push(p);
			p = p->Lchild;
		}
		if(!v.empty()) {
			p = v.top();
			v.pop();
			p = p->Rchild;
		}
	}
}

void nPostorder(Bit root) {
	stack<Bit> s;
	Bit cur;
	Bit pre = NULL;
	s.push(root);
	while (!s.empty()) {
		cur = s.top();
		if ((cur->Rchild == NULL && cur->Lchild == NULL) || (pre != NULL && (pre == cur->Lchild || pre == cur->Rchild))) {
			visit(cur->data);
			s.pop();
			pre = cur;
		}
		else {
			if (cur->Rchild != NULL) {
				s.push(cur->Rchild);
			}
			if (cur->Lchild != NULL) {
					s.push(cur->Lchild);
			}
		}
	}
}
#endif // !BITREENRC_H

Main.cpp

#include "BiTreeRC.h"
#include "BiTreeNRC.h"
void Recursion(Bit b);
void Nonrecursion(Bit b);

int main() {
	Bit b;
	cout << "***请输入树,格式按照先序遍历进行输入***" << endl;
	CreatBit(&b);
	Recursion(b);
	Nonrecursion(b);
}

void Recursion(Bit b) {
	cout << "\n递归算法" << endl;
	cout << "\n先序遍历" << endl;
	Preorder(b);
	cout << "\n中序遍历" << endl;
	Inorder(b);
	cout << "\n后序遍历" << endl;
	Postorder(b);
}

void Nonrecursion(Bit b) {
	cout << "非递归算法(栈)" << endl;
	cout << "\n先序遍历" << endl;
	nPreorder(b);
	cout << "\n中序遍历" << endl;
	nInorder(b);
	cout << "\n后序遍历" << endl;
	nPostorder(b);
}

运行展示
在这里插入图片描述

C语言非递归版

#include<stdio.h>
#include<stdlib.h>
#define BiTreeNode char
#define TRUE 1
#define FALSE 0
#define MAX_SIZE 50
#define StackElementType BiTree

typedef struct Node
{
	BiTreeNode data;
	struct Node *LChild;
	struct Node *RChild;
}Node,*BiTree;

typedef struct
{
	StackElementType elem[MAX_SIZE];
	int top;
}Stack;

void InitStack(Stack **S)  //初始化
{
	*S=(Stack*)malloc(sizeof(Stack));
	(*S)->top=-1;
}


int IsEmpty(Stack **S)  //判空
{
	return ((*S)->top==-1?TRUE:FALSE);
}

int IsFull(Stack **S)  //判满
{
	return ((*S)->top==MAX_SIZE-1?TRUE:FALSE);
}

int Push(Stack **S,StackElementType x) //进栈
{
	if((*S)->top==MAX_SIZE-1)
		return (FALSE);
	(*S)->top++;
	(*S)->elem[(*S)->top]=x;
	return (TRUE);
}

int Pop(Stack **S,StackElementType *x)  //出栈
{
	if((*S)->top==-1)
		return (FALSE);
	else
	{
		*x=(*S)->elem[(*S)->top];
		(*S)->top--;
		return (TRUE);
	}
}

int GetTop(Stack **S,StackElementType *x)  //取栈顶元素
{
	if((*S)->top==-1)
		return (FALSE);
	else
	{
		*x=(*S)->elem[(*S)->top];
		return (TRUE);
	}
}

void Visit(BiTreeNode data)  //访问结点数据
{
	putchar(data);
}

void CreateBiTree(BiTree *bt)  //创建二叉树
{
	char ch;
	ch=getchar();
	if (ch=='.')
		*bt=NULL;
	else
	{
		*bt=(BiTree)malloc(sizeof(Node));
		(*bt)->data=ch;
		CreateBiTree(&((*bt)->LChild));
		CreateBiTree(&((*bt)->RChild));
	}
}

void PreOrder(BiTree root)  //先序遍历
{
	Stack *s;
	BiTree temp=root;
	InitStack(&s);
	while (temp!= NULL||IsEmpty(&s)!=TRUE)
	{
		while (temp!= NULL)
		{
			Visit(temp->data);	//访问根节点
			if(IsFull(&s)==TRUE)
				return;
			Push(&s,temp);	//根指针进栈
			temp=temp->LChild;	//遍历左子树
		}
		if(IsEmpty(&s)!=TRUE)
		{
			Pop(&s,&temp);	//根指针弹栈
			temp=temp->RChild;	//遍历右子树
		}
	}
}

void InOrder(BiTree root)  //中序遍历
{
	Stack *s;
	BiTree temp=root;
	InitStack(&s);
	while(temp!=NULL||IsEmpty(&s)!=TRUE)
	{
		while(temp!=NULL)
		{
			if(IsFull(&s)==TRUE)
				return;
			Push(&s,temp); //根指针进栈
			temp=temp->LChild; //遍历左子树
		}
		if(IsEmpty(&s)!=TRUE)
		{
			Pop(&s,&temp);	//根指针弹栈
			Visit(temp->data); //访问根节点
			temp=temp->RChild; //遍历右子树
		}
	}
}


void PostOrder(BiTree root)  //后序遍历
{
	Stack *s;
	BiTree temp=root,flag=NULL;
	InitStack(&s);
	while(temp!=NULL||IsEmpty(&s)!= TRUE)
	{
		while(temp!= NULL)
		{
			if(IsFull(&s)==TRUE)
				return;
			Push(&s,temp);	//根指针进栈
			temp=temp->LChild;	//遍历左子树
		}
		if(IsEmpty(&s)!=TRUE)
		{
			GetTop(&s,&temp);
			if(temp->RChild==NULL||temp->RChild==flag)
			{
				Pop(&s,&temp);	//根指针弹栈
				Visit(temp->data);	//访问根节点
				flag=temp;
				temp=NULL;
			}
			else
				temp=temp->RChild;	//遍历右子树
		}
	}
}

int main()
{
	BiTree bt=NULL;
	printf("请按先序序列输入一颗二叉树的结点数据,以'.'来代表空值:");
	CreateBiTree(&bt);
	printf("先序序列:");
	PreOrder(bt);
	printf("\n中序序列:");
	InOrder(bt);
	printf("\n后序序列:");
	PostOrder(bt);
	putchar('\n');
	return 0;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是二叉树的遍历方法: 1. 先序遍历(DLR):先访问根节点,然后递归地先序遍历左子树,最后递归地先序遍历右子树。 2. 中序遍历(LDR):先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。 3. 后序遍历(LRD):先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。 4. 层次遍历:从上到下逐层遍历二叉树的节点。 以下是一个示例代码,演示了如何实现二叉树的遍历: ```python class Node: def __init__(self, value): self.value = value self.left = None self.right = None def preorder_traversal(root): if root is None: return print(root.value) preorder_traversal(root.left) preorder_traversal(root.right) def inorder_traversal(root): if root is None: return inorder_traversal(root.left) print(root.value) inorder_traversal(root.right) def postorder_traversal(root): if root is None: return postorder_traversal(root.left) postorder_traversal(root.right) print(root.value) def level_order_traversal(root): if root is None: return queue = [root] while queue: node = queue.pop(0) print(node.value) if node.left: queue.append(node.left) if node.right: queue.append(node.right) # 创建二叉树 root = Node(1) root.left = Node(2) root.right = Node(3) root.left.left = Node(4) root.left.right = Node(5) # 先序遍历 print("先序遍历:") preorder_traversal(root) # 中序遍历 print("中序遍历:") inorder_traversal(root) # 后序遍历 print("后序遍历:") postorder_traversal(root) # 层次遍历 print("层次遍历:") level_order_traversal(root) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值