8608实现二叉排序树的各种算法(2)

 

Description

用函数实现如下二叉排序树算法: 
(1) 插入新结点 
(2) 前序、中序、后序遍历二叉树 
(3) 中序遍历的非递归算法 
(4) 层次遍历二叉树 
(5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0) 
(6) 交换各结点的左右子树 
(7) 求二叉树的深度 
(8) 叶子结点数

输入格式

第一行:准备建树的结点个数n 
第二行:输入n个整数,用空格分隔 
第三行:输入待查找的关键字 
第四行:输入待查找的关键字 
第五行:输入待插入的关键字

输出格式

第一行:二叉树的先序遍历序列 
第二行:二叉树的中序遍历序列 
第三行:二叉树的后序遍历序列 
第四行:查找结果 
第五行:查找结果 
第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列 
第九行:插入新结点后的二叉树的中序遍历序列(非递归算法) 
第十行:插入新结点后的二叉树的层次遍历序列 
第十一行~第十三行:第一次交换各结点的左右子树后的先、中、后序遍历序列 
第十四行~第十六行:第二次交换各结点的左右子树后的先、中、后序遍历序列 
第十七行:二叉树的深度 
第十八行:叶子结点数

输入样例

7
40 20 60 18 50 56 90
18
35
30

输出样例

40 20 18 60 50 56 90
18 20 40 50 56 60 90
18 20 56 50 90 60 40
1
0
40 20 18 30 60 50 56 90
18 20 30 40 50 56 60 90
18 30 20 56 50 90 60 40
18 20 30 40 50 56 60 90
40 20 60 18 30 50 90 56
40 60 90 50 56 20 30 18
90 60 56 50 40 30 20 18
90 56 50 60 30 18 20 40
40 20 18 30 60 50 56 90
18 20 30 40 50 56 60 90
18 30 20 56 50 90 60 40
4
4

使用C语言模拟实现C++STL库内栈和队列的基本操作

代码如下:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stack>
#include <queue>
#include <assert.h>

using namespace std;

typedef int ElemType;// 定义二叉排序树元素类型

typedef struct BSTNode//二叉排序树的结点类型
{
	ElemType data;
	struct BSTNode* lchild;
	struct BSTNode* rchild;
}BSTNode,*BSTree;

void BSTNodeInsert(BSTree& T, ElemType x)
{
	//二叉排序树结点的插入
	if (T == NULL)//开始树为空或者找到插入位置,递归结束
	{
		BSTNode* newnode = (BSTNode*)malloc(sizeof(BSTNode));
		newnode->data = x;
		newnode->lchild = NULL;
		newnode->rchild = NULL;
		T = newnode;
	}
	else//树不为空,查找插入位置
	{
		if (x > T->data)//大的向右
		{
			BSTNodeInsert(T->rchild, x);
		}
		else if (x < T->data)//小的向左
		{
			BSTNodeInsert(T->lchild, x);
		}
	}
}

void CreatBSTree(BSTree& T)
{
	//构建n个结点的二叉排序树
	int n = 0;
	cin >> n;
	while (n--)
	{
		ElemType val = 0;
		cin >> val;
		BSTNodeInsert(T, val);
	}
}

void PreOrderTraverse(BSTree& T)
{
	//二叉排序树的先序遍历(递归写法)
	if (T!=NULL)
	{
		printf("%d ", T->data);
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
}

void InOrderTraverse(BSTree& T)
{
	//二叉排序树的中序遍历(递归写法)
	if (T != NULL)
	{
		InOrderTraverse(T->lchild);
		printf("%d ", T->data);
		InOrderTraverse(T->rchild);
	}
}

void PostOrderTraverse(BSTree& T)
{
	//二叉排序树的后序遍历(递归写法)
	if (T != NULL)
	{
		PostOrderTraverse(T->lchild);
		PostOrderTraverse(T->rchild);
		printf("%d ", T->data);
	}
}

typedef struct Stack
{
	BSTree* base;// 在栈初始化和销毁之后,base的值为NULL
	BSTree* top;// 栈顶指针
	int capacity;// 当前已分配的存储空间,以元素为单位
}Stack;// 顺序栈

#define STACK_INIT_SIZE 100// 存储空间初始分配量
#define STACKINCREMENT  10// 存储空间分配增量

void StackInit(Stack& S)
{
	//构造一个空栈S
	S.base = S.top = NULL;
	S.capacity = 0;
}

void StackPush(Stack& S, BSTree x)
{
	// 在栈S中插入元素x为新的栈顶元素
	if (S.top - S.base == S.capacity)//栈的容量已满
	{
		//扩容
		int newCapacity = S.capacity == 0 ? STACK_INIT_SIZE : S.capacity + STACKINCREMENT;//首次分配空间为STACK_INIT_SIZE,之后每次增加STACKINCREMENT
		BSTree* tmp = (BSTree*)realloc(S.base,sizeof(BSTree) * newCapacity);
		if (tmp == NULL)
		{
			cout << "StackPush malloc failed" << endl;
			exit(-1);
		}
		S.base = tmp;
		S.top = S.base + S.capacity;
		S.capacity = newCapacity;
	}
	*S.top = x;//插入元素
	S.top++;
}

bool StackEmpty(Stack& S)
{
	//判断栈S是否为空,为空返回true,不为空返回false
	return S.top - S.base == 0;
}

void StackPop(Stack& S)
{
	// 若栈不空,则删除S的栈顶元素
	assert(!StackEmpty(S));
	S.top--;
}

size_t StackSize(Stack& S)
{
	// 返回栈S的元素个数
	return S.top - S.base;
}

BSTree StackTop(Stack& S)
{
	// 若栈不空,则返回S的栈顶元素
	assert(!StackEmpty(S));
	return *(S.top - 1);
}

void StackDestroy(Stack& S)
{
	//销毁栈S
	free(S.base);
	S.base = S.top = NULL;
	S.capacity = 0;
}

void InOrderTraverse_by_Stack(BSTree& T)
{
	//二叉排序树的中序遍历(非递归写法),借助栈来实现
	Stack S;
	StackInit(S);
	BSTree cur = T;
	while (cur != NULL || !StackEmpty(S))//当前结点为空且栈为空,结束循环
	{
		while (cur)//向左走到尽头,将沿途结点压进栈
		{
			StackPush(S, cur);//根结点进栈
			cur = cur->lchild;//遍历左子树
		}
		cur = StackTop(S);//根结点出栈
		printf("%d ", cur->data);
		cur = cur->rchild;//遍历右子树
		StackPop(S);
	}
	StackDestroy(S);
}

typedef struct QueueNode
{
	BSTree ptr;
	struct QueueNode* next;
}QueueNode;//链式队列的结点类型

typedef struct Queue
{
	QueueNode* head;//队列头指针
	QueueNode* tail;//队列尾指针
}Queue;//链式队列

void QueueInit(Queue& Q)
{
	//构造一个空队列Q
	Q.head = Q.tail = NULL;
}

void QueuePush(Queue& Q, BSTree x)
{
	// 在队列Q中插入元素x为新的队尾元素
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		cout << "QueuePush malloc failed" << endl;
		exit(-1);
	}
	newnode->ptr = x;
	newnode->next = NULL;
	//插入元素
	if (Q.head == NULL)//队列为空
	{
		Q.head = newnode;
		Q.tail = newnode;
	}
	else//队列已有元素
	{
		Q.tail->next = newnode;
		Q.tail = newnode;
	}
}

bool QueueEmpty(Queue& Q)
{
	//判断队列Q是否为空,为空返回true,不为空返回false
	return Q.head == NULL;
}

void QueuePop(Queue& Q)
{
	//若队列Q不为空,删除队头元素
	assert(!QueueEmpty(Q));
	QueueNode* next = Q.head->next;
	free(Q.head);
	Q.head = next;
	if (Q.head == NULL)//当队列删为空,把tail置为空,防止野指针
	{
		Q.tail = NULL;
	}
}

BSTree QueueFront(Queue& Q)
{
	//若队列Q不为空,返回队头元素
	assert(!QueueEmpty(Q));
	return Q.head->ptr;
}

BSTree QueueBack(Queue& Q)
{
	//若队列Q不为空,返回队尾元素
	assert(!QueueEmpty(Q));
	return Q.tail->ptr;
}

size_t QueueSize(Queue& Q)
{
	//返回队列Q的元素个数
	size_t size = 0;
	QueueNode* cur = Q.head;
	while (cur != NULL)
	{
		size++;
	}
	return size;
}

void QueueDestroy(Queue& Q)
{
	//销毁队列
	QueueNode* cur = Q.head;
	while (cur != NULL)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	Q.head = Q.tail = NULL;
}

void LevelTraverse(BSTree& T)
{
	//二叉排序树的层次遍历,借助队列来实现
	Queue Q;
	QueueInit(Q);
	if (T != NULL)//开始树不为空
	{
		QueuePush(Q, T);
	}
	while (!QueueEmpty(Q))//队列不为空
	{
		BSTree cur = QueueFront(Q);//取队头元素
		printf("%d ", cur->data);
		if (cur->lchild != NULL)//左子树不为空,左子树入队
		{
			QueuePush(Q, cur->lchild);
		}
		if (cur->rchild != NULL)//右子树不为空,右子树入队
		{
			QueuePush(Q, cur->rchild);
		}
		QueuePop(Q);//已遍历完成的结点出队
	}
	QueueDestroy(Q);
}

int BSTreeSearch(BSTree& T, ElemType x)
{
	//二叉排序树的查找,找到返回1,没找到返回0
	if (T == NULL)//开始树为空或者查找到尽头,查找失败,返回0
	{
		return 0;
	}
	else if (T->data == x)//查找成功,返回1
	{
		return 1;
	}
	else if (x > T->data)//大于向右找
	{
		return BSTreeSearch(T->rchild, x);
	}
	else if (x < T->data)//小于向左找
	{
		return BSTreeSearch(T->lchild, x);
	}
}

void SubTreeSwap(BSTree& T)
{
	//交换各结点的左右子树
	if (T != NULL && (T->lchild != NULL || T->rchild != NULL))//当前结点不为空,且左右子树不全为空
	{
		//交换当前结点的左右子树
		BSTree tmp = T->lchild;
		T->lchild = T->rchild;
		T->rchild = tmp;
		SubTreeSwap(T->lchild);//交换当前结点左子树的左右子树
		SubTreeSwap(T->rchild);//交换当前结点右子树的左右子树
	}
}

size_t Depth(BSTree& T)
{
	//二叉树的深度
	if (T == NULL)//空树返回0,不能省略
	{
		return 0;
	}
	else
	{
		size_t m = Depth(T->lchild);//左子树深度
		size_t n = Depth(T->rchild);//右子树深度
		return m > n ? m + 1 : n + 1;//当前结点深度=左右子树中较大的一个+1
	}
}

size_t LeafNumbers(BSTree& T)
{
	if (T == NULL)//空树返回0,不能省略
	{
		return 0;
	}
	else
	{
		if (T->lchild == NULL && T->rchild == NULL)//当前结点是叶子结点,返回1
		{
			return 1;
		}
		else
		{
			return LeafNumbers(T->lchild) + LeafNumbers(T->rchild);//当前结点不是叶子结点,统计左右子树的叶子结点之和
		}
	}
}

void BSTreeDestory(BSTree& T)
{
	//销毁二叉树
	if (T != NULL)
	{
		BSTree left = T->lchild;
		BSTree right = T->rchild;
		free(T);
		T = NULL;
		BSTreeDestory(left);
		left = NULL;
		BSTreeDestory(right);
		right = NULL;
	}
}

int main()
{
	BSTree T=NULL;
	//构建二叉排序树
	CreatBSTree(T);
	//先序遍历(递归写法)
	PreOrderTraverse(T);
	cout << endl;
	//中序遍历(递归写法)
	InOrderTraverse(T);
	cout << endl;
	//后序遍历(递归写法)
	PostOrderTraverse(T);
	cout << endl;

	int x = 0;
	cin >> x;//查找x
	cout << BSTreeSearch(T, x) << endl;
	cin >> x;//查找x
	cout << BSTreeSearch(T, x) << endl;

	cin >> x;//插入x
	BSTNodeInsert(T, x);
	//先序遍历(递归写法)
	PreOrderTraverse(T);
	cout << endl;
	//先序遍历(递归写法)
	InOrderTraverse(T);
	cout << endl;
	//后序遍历(递归写法)
	PostOrderTraverse(T);
	cout << endl;
	//中序遍历(非递归写法)
	InOrderTraverse_by_Stack(T);
	cout << endl;
	//层次遍历
	LevelTraverse(T);
	cout << endl;
	//交换左右子树
	SubTreeSwap(T);
	//先序遍历(递归写法)
	PreOrderTraverse(T);
	cout << endl;
	//中序遍历(递归写法)
	InOrderTraverse(T);
	cout << endl;
	//后序遍历(递归写法)
	PostOrderTraverse(T);
	cout << endl;
	//交换左右子树
	SubTreeSwap(T);
	//先序遍历(递归写法)
	PreOrderTraverse(T);
	cout << endl;
	//中序遍历(递归写法)
	InOrderTraverse(T);
	cout << endl;
	//后序遍历(递归写法)
	PostOrderTraverse(T);
	cout << endl;
	//树的深度
	cout << Depth(T) << endl;
	//树的叶子结点数
	cout << LeafNumbers(T) << endl;
	//销毁二叉树
	BSTreeDestory(T);
	return 0;
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值