二叉树的生成与遍历实验

1.实验目的

(1)掌握二叉树的结构特性和二叉链表存储结构。

(2)掌握二叉树遍历的递归和非递归方法。

2.实验内容

(1)假设二叉树采用链接存储方式存储,分别编写一个二叉树先序遍历的递归 算法和非递归算法。

3. 具体实现

3.1 二叉树的生成

 3.1.1 构建二叉树结点的结构体

//定义每个结点的结构体
struct biTreeNode
{
	//数据域
	char data;
	//左孩子与右孩子
	biTreeNode* leftChild, * rightChild;
};

3.1.2 创建二叉树类来对二叉树进行操作

//构建二叉树类
class BiTree
{
public:
	BiTree();
	~BiTree();
	void preOrder() {
		cout << "递归先序遍历二叉树:" ;
		preOrder(root);
		cout << endl;
	}
	void npreOrder() {
		cout << "非递归先序遍历二叉树:";
		npreOrder(root);
		cout << endl;
	}
private:
	biTreeNode* root;
	biTreeNode* creatBiTree(biTreeNode* T);
	void Release(biTreeNode* T);
	void preOrder(biTreeNode* T);
	void npreOrder(biTreeNode* T);
};

3.1.2 我们规定二叉树以先序遍历序列(前序遍历)来输入生成二叉树。

        若二叉树为空,则空操作返回;否则:

        (1)访问结点

        (2遍历结点的左子树

        (3遍历结点的右子

        注意:此处输入方式规定 '#' 为该结点为空结点

 

代码如下:

biTreeNode* BiTree::creatBiTree(biTreeNode* T) {

	char ch;
	cin >> ch;
	//如果输入的是'#'则是空结点
	if (ch == '#') {
		T = NULL;
	}
	else {
		//分配空间
		T = new biTreeNode;
		//数据域赋值
		T->data = ch;
		//先序遍历递归赋值
		T->leftChild = creatBiTree(T->leftChild);
		T->rightChild = creatBiTree(T->rightChild);
	}
	//返回树的根节点
	return T;
}

3.2 递归遍历二叉树

传入二叉树的根节点,与上面构建二叉树的前序遍历法一样进行递归实现

void BiTree::preOrder(biTreeNode* T) {
	//递归算法,先序遍历输出
	if (T != NULL) {
		cout << T->data << ' ';
		preOrder(T->leftChild);
		preOrder(T->rightChild);
	}
}

3.3 非递归遍历二叉树

        递归算法中编译器自动生成了栈为我们存储了函数的返回值(我是这么理解的哈哈,希望大佬指正),所以我们在非递归算法中自然而然要用到栈来保存数据。在先序遍历过某结点的整个左子树后,如何找到该结点的右子树的根指针。需要定义一个堆栈存放遍历过的结点 的指针,以便能通过它找到该结点的右子树。而栈就刚好满足了后进先出的条件。

一般情况下,设要遍历的二叉树的根指针为bt,可能有两种情况:
(a)若 bt!=NULL,则表明当前的二叉树不为空,此时,输出根结点 bt 的值并 将 bt 保存到栈中,准备继续遍历 bt 的左子树。
(b)若 bt==NULL,则表明以 bt 为根指针的二叉树遍历完毕,并且 bt 是栈顶指 针所指结点的左子树,若栈不空,则应根据栈顶指针所指结点找到待遍历右子树的根 指针并赋给 bt,以继续遍历下去;若栈空,则表明整个二叉树遍历完毕,应结束。

/*
1. 栈 s 初始化:
	1.1 创建biTreeNode* 类型数组;
	1.2 栈顶指针top初始化为-1;
2.循环直到 bt 为空且栈 s 为空;
	2.1 当 bt 不空时循环
		2.1.1 输出 bt->data;
		2.1.2 将指针 bt 保存在栈中;
		2.1.3 继续遍历 bt 的左子树;
	2.2 如果栈 s 不空,则
		2.2.1 将栈顶元素弹出至 bt;
		2.2.2 准备遍历 bt 的右子树;
*/
void BiTree::npreOrder(biTreeNode* T) {
	
	//非递归先序遍历二叉树算法

	biTreeNode* s[100];
	int top = -1;
	while (T != NULL || top != -1) {
		while (T != NULL) {
			cout << T->data << ' ';
			s[++top] = T;
			T = T->leftChild;
		}
		if (top != -1) {
			T = s[top--];
			T = T->rightChild;
		}
	}
}

3.4 完整代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

//定义每个结点的结构体
struct biTreeNode
{
	//数据域
	char data;
	//左孩子与右孩子
	biTreeNode* leftChild, * rightChild;
};

//构建二叉树类
class BiTree
{
public:
	BiTree();
	~BiTree();
	void preOrder() {
		cout << "递归先序遍历二叉树:" ;
		preOrder(root);
		cout << endl;
	}
	void npreOrder() {
		cout << "非递归先序遍历二叉树:";
		npreOrder(root);
		cout << endl;
	}
private:
	biTreeNode* root;
	biTreeNode* creatBiTree(biTreeNode* T);
	void Release(biTreeNode* T);
	void preOrder(biTreeNode* T);
	void npreOrder(biTreeNode* T);
};

BiTree::BiTree()
{
	cout << "请按照先序遍历的顺序输入二叉树的元素,空结点用'#'代替" << endl;
	//返回二叉树的根节点
	root = creatBiTree(root);
}

BiTree::~BiTree()
{
	//销毁空间
	Release(root);
}

void BiTree::Release(biTreeNode* T) {
	//递归算法,后序遍历销毁空间
	if (T != NULL) {
		Release(T->leftChild);
		Release(T->rightChild);
		delete T;
	}
}

biTreeNode* BiTree::creatBiTree(biTreeNode* T) {

	char ch;
	cin >> ch;
	//如果输入的是'#'则是空结点
	if (ch == '#') {
		T = NULL;
	}
	else {
		//分配空间
		T = new biTreeNode;
		//数据域赋值
		T->data = ch;
		//先序遍历递归赋值
		T->leftChild = creatBiTree(T->leftChild);
		T->rightChild = creatBiTree(T->rightChild);
	}
	//返回树的根节点
	return T;
}

void BiTree::preOrder(biTreeNode* T) {
	//递归算法,先序遍历输出
	if (T != NULL) {
		cout << T->data << ' ';
		preOrder(T->leftChild);
		preOrder(T->rightChild);
	}
}

/*
1. 栈 s 初始化:
	1.1 创建biTreeNode* 类型数组;
	1.2 栈顶指针top初始化为-1;
2.循环直到 bt 为空且栈 s 为空;
	2.1 当 bt 不空时循环
		2.1.1 输出 bt->data;
		2.1.2 将指针 bt 保存在栈中;
		2.1.3 继续遍历 bt 的左子树;
	2.2 如果栈 s 不空,则
		2.2.1 将栈顶元素弹出至 bt;
		2.2.2 准备遍历 bt 的右子树;
*/
void BiTree::npreOrder(biTreeNode* T) {
	
	//非递归先序遍历二叉树算法

	biTreeNode* s[100];
	int top = -1;
	while (T != NULL || top != -1) {
		while (T != NULL) {
			cout << T->data << ' ';
			s[++top] = T;
			T = T->leftChild;
		}
		if (top != -1) {
			T = s[top--];
			T = T->rightChild;
		}
	}
}

void test();
void test() {
	BiTree bi;
	bi.preOrder();
	bi.npreOrder();
	system("pause");
}

int main() {
	test();
}

通过此次实验,加深了我对递归算法的熟练度,之前真的看到递归就烦。。。

二叉树生成可以通过多种方式实现,包括手动输入节点信息、读入文件等。在手动输入节点信息时,可以按照前序遍历的方式输入节点信息,当输入到空节点时使用特殊字符(如“#”或“null”)表示。 以下是一个手动输入节点信息生成二叉树的示例代码: ```python class TreeNode: def __init__(self, value): self.val = value self.left = None self.right = None def build_tree(): val = input('请输入节点的数值,空节点使用“#”表示:') if val == '#': return None node = TreeNode(int(val)) node.left = build_tree() node.right = build_tree() return node ``` 这个代码中,我们定义了一个 `TreeNode` 类表示二叉树的节点,然后定义了一个 `build_tree` 函数来递归地构建二叉树。在函数中,我们首先输入节点的数值,如果是空节点则返回 `None`,否则创建一个节点对象并递归构建其左右子树。 二叉树遍历包括前序遍历、中序遍历和后序遍历。以下是三种遍历方式的示例代码: ```python def preorder_traversal(root): if root is None: return print(root.val, end=' ') preorder_traversal(root.left) preorder_traversal(root.right) def inorder_traversal(root): if root is None: return inorder_traversal(root.left) print(root.val, end=' ') inorder_traversal(root.right) def postorder_traversal(root): if root is None: return postorder_traversal(root.left) postorder_traversal(root.right) print(root.val, end=' ') ``` 这些函数都接受一个二叉树的根节点作为参数,然后按照不同的顺序遍历二叉树并输出节点的数值。其中,前序遍历首先访问根节点,然后依次遍历左子树和右子树;中序遍历首先遍历左子树,然后访问根节点,最后遍历右子树;后序遍历则是先遍历左右子树,最后访问根节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值