二叉树遍历、结点数、左右子树交换和二叉排序树的插入删除

二叉树用二叉链表表示 (独立完成)
设计内容:
(1) 实现二叉树的建立、前序、中序(非递归)和层次遍历;
(2) 求二叉树高度、结点数、度为 1 的结点数和叶子结点数;
(3) 插入结点到指定位置、删除指定结点;
(4) 将二叉树所有结点的左右子树交换。

代码实现:

二叉树和二叉排序树的结构体当时是可以用一个表示的,当时时间有限懒得改了。

#include <iostream>
#include <string>
#include <queue>
#include <stack>
using namespace std;

#define MAXSIZE 100
typedef int ElemType;

//二叉树
typedef struct BiTNode {
	ElemType data;
	struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;

//二叉排序树
typedef struct BSTNode
{
	int data;
	BSTNode* lchild;  //左孩子
	BSTNode* rchild;  //右孩子
}BSTNode, * BSTree;

//中序遍历的非递归方法
void InTraverse(BiTree tree)
{
	stack<BiTree> s;
	BiTree p = tree;
	BiTree q = new BiTNode;
	while (p || !s.empty())
	{
		if (p)
		{
			s.push(p);
			p = p->lchild;
		}
		else
		{
			q = s.top();
			s.pop();
			cout << q->data<<' ';
			p = q->rchild;
		}
	}
}

//先序
void preorderTraverse(BiTree T)
{
	if (T)
	{
		cout << T->data;
		preorderTraverse(T->lchild);
		preorderTraverse(T->rchild);
	}
}

//后序
void postorderTraverse(BiTree t)
{
	if (t)
	{
		postorderTraverse(t->lchild);
		postorderTraverse(t->rchild);
		cout << t->data;
	}
}

//先序建立二叉链表
void create_bitree(BiTree& t)
{
	int c;
	cin >> c;
		if (c == 0)
		{
			t = NULL;
			cout << "retunr";
		}
		else
		{
			t = new BiTNode;
			t->data = c;
			create_bitree(t->lchild);
			create_bitree(t->rchild);
		}
}

//层次遍历
void BinaryTreeLevelOrder(BiTree root)
{
	queue<BiTNode*> q;
	if(root == NULL)
	{
		return;
	}
	q.push(root);
	while (!q.empty())
	{
		//出队保存队头并访问
		BiTree front = q.front();
		cout << front->data <<' ';
		q.pop();
		//将出队节点的左子树根入队
		if (front->lchild)
			q.push(front->lchild);
		//将出队节点的右子树根入队
		if (front->rchild)
			q.push(front->rchild);
	}

}

//树的高度
int height(BiTree T)
{
	if (T == NULL)
		return 0;
	else
	{
		int m = height(T->lchild);
		int n = height(T->rchild);
		return (m > n) ? (m + 1) : (n + 1);
	}
}

//结点数
int count(BiTree t)
{
	if (t == NULL)
		return 0;
	else
		return count(t->lchild) + count(t->rchild) + 1;
}

//度为1结点数
int leaf_1(BiTree t)
{
	if (t == NULL)
		return 0;
	if ((t->lchild == NULL && t->rchild != NULL) || (t->lchild != NULL && t->rchild == NULL))
	{
		return 1 + leaf_1(t->lchild) + leaf_1(t->rchild);
	}
	return leaf_1(t->lchild) + leaf_1(t->rchild);
}

//叶子节点数
int leaves(BiTree t)
{
	if (t == NULL)
		return 0;
	if (t->lchild == NULL && t->rchild == NULL)
		return 1;
	return leaves(t->lchild) + leaves(t->rchild);
}

//将二叉树中所欲节点的左右子树相互交换
BiTree exchange(BiTree t)
{
	BiTree p;
	if (t == NULL || (t->lchild == NULL && t->rchild == NULL))
		return t;
	p = t->lchild;
	t->lchild = t->rchild;
	t->rchild = p;
	if (t->lchild)
		t->lchild = exchange(t->lchild);
	if (t->rchild)
		t->rchild = exchange(t->rchild);
	return t;
}

//树的高度0
int height(BSTree T)
{
	if (T == NULL)
		return 0;
	else
	{
		int m = height(T->lchild);
		int n = height(T->rchild);
		return (m > n) ? (m + 1) : (n + 1);
	}
}

//结点数0
int count(BSTree t)
{
	if (t == NULL)
		return 0;
	else
		return count(t->lchild) + count(t->rchild) + 1;
}

//度为1结点数0
int leaf_1(BSTree t)
{
	if (t == NULL)
		return 0;
	if ((t->lchild == NULL && t->rchild != NULL) || (t->lchild != NULL && t->rchild == NULL))
	{
		return 1 + leaf_1(t->lchild) + leaf_1(t->rchild);
	}
	return leaf_1(t->lchild) + leaf_1(t->rchild);
}

//叶子节点数0
int leaves(BSTree t)
{
	if (t == NULL)
		return 0;
	if (t->lchild == NULL && t->rchild == NULL)
		return 1;
	return leaves(t->lchild) + leaves(t->rchild);
}

bool Search(BSTree bst, int key, BSTree f, BSTree* p);

void InOderTraverse(BSTree bst)   //中序递归遍历二叉树
{
	if (NULL != bst)
	{
		InOderTraverse(bst->lchild);
		printf("%d ", bst->data);
		InOderTraverse(bst->rchild);
	}
}

//创建排序树
static BSTNode* BuyNode(int data)   //生成一个节点并进行初始化
{
	BSTNode* pTmp = (BSTNode*)malloc(sizeof(BSTNode));
	if (NULL == pTmp)
	{
		exit(0);
	}
	pTmp->data = data;
	pTmp->lchild = NULL;
	pTmp->rchild = NULL;
	return pTmp;
}

//插入
bool Insert(BSTree* bst, int key)
{
	if (NULL == *bst)  //空树
	{
		*bst = BuyNode(key);   //插入根节点
		return true;
	}
	BSTNode* p;
	//先在二叉排序树中查找要插入的值是否已经存在
	if (!Search(*bst, key, NULL, &p))  //如果查找失败,则插入;此时p指向遍历的最后一个节点
	{
		BSTNode* pNew = BuyNode(key);
		if (key < p->data)  //将s作为p的左孩子
		{
			p->lchild = pNew;
		}
		else if (key > p->data)  //将s作为p的右孩子
		{
			p->rchild = pNew;
		}
		return true;  //插入成功
	}
	else
	{
		printf("\nThe node(%d) already exists.\n", key);
	}
	return false;
}

BSTNode* FindParent(BSTree bst, BSTNode* child)
{
	if (NULL == bst)
	{
		return NULL;
	}

	if (bst->lchild == child || bst->rchild == child)
	{
		return bst;
	}
	else if (NULL != bst->lchild)
	{
		FindParent(bst->lchild, child);
	}
	else if (NULL != bst->rchild)
	{
		FindParent(bst->rchild, child);
	}
}

//删除
void Delete(BSTree* bst, int key)
{
	if (NULL == *bst)
	{
		exit(1);  //空树直接报错
	}
	BSTNode* p;
	BSTNode* f = NULL;
	BSTNode* q, * s;
	if (Search(*bst, key, NULL, &p)) //确实存在值为key的节点,则p指向该节点
	{

		if (NULL == p->lchild && NULL != p->rchild)  //无左孩子,有右孩子
		{
			q = p->rchild;
			p->data = q->data;    //因为两个节点之间本质的不同在于数据域的不同,而与放在哪个地址没有关系
			p->rchild = q->rchild;
			p->lchild = q->lchild;
			free(q);
		}
		else if (NULL == p->rchild && NULL != p->lchild)  //无右孩子,有左孩子
		{
			q = p->lchild;
			p->data = q->data;
			p->rchild = q->rchild;
			p->lchild = q->lchild;
			free(q);
		}
		else if (NULL != p->rchild && NULL != p->lchild) //既有左孩子,又有右孩子
		{
			q = p;
			s = p->lchild;   //找左孩子的最右孩子
			while (s->rchild)
			{
				q = s;
				s = s->rchild;
			}
			p->data = s->data;

			if (q != p)
			{
				q->rchild = p->lchild;
			}
			else
			{
				q->lchild = s->lchild;
			}
			free(s);
		}
		else
		{
			if (*bst == p)   //只有一个根节点
			{
				free(*bst);
				*bst = NULL;
				return;
			}

			BSTNode* parent = FindParent(*bst, p);
			if (parent->lchild == p)
			{
				parent->lchild = NULL;
			}
			else
			{
				parent->rchild = NULL;
			}
			free(p);
		}
	}
}

bool Search(BSTree bst, int key, BSTree f, BSTree* p)  //查找成功时,p指向值为key的节点。如果查找失败,则p指向遍历的最后一个节点
{
	if (!bst)
	{
		*p = f;
		return false;
	}
	if (bst->data == key)  //查找成功,直接返回
	{
		*p = bst;
		return true;
	}
	else if (bst->data < key)
	{
		return Search(bst->rchild, key, bst, p);
	}
	return Search(bst->lchild, key, bst, p);
}

void test()
{
	BSTNode* root = NULL;
	Insert(&root, 45);
	Insert(&root, 24);
	Insert(&root, 53);
	Insert(&root, 12);
	Insert(&root, 90);
	cout << "插入后:" << endl;
	InOderTraverse(root);
	cout << endl;
	cout << "输出0表示插入失败,输出1表示插入成功(插入4成功,45失败)" << endl;
	printf("\n%d ", Insert(&root, 45));   //输出0表示插入失败,输出1表示插入成功
	printf("%d\n", Insert(&root, 4));
	cout << "遍历结果:" << endl;
	InOderTraverse(root);
	printf("\n");
	//Delete(&root, 4);      //删除节点45
	Delete(&root, 45);      //删除节点45
	//Delete(&root, 24);      //删除节点45
	Delete(&root, 53);      //删除节点45
	//Delete(&root, 12);      //删除节点45
	Delete(&root, 90);      //删除节点45
	cout << "删除45,53,90后遍历结果:" << endl;
	InOderTraverse(root);
	cout << endl;
	int t;
	cout << "1.插入" << endl;
	cout << "2.删除" << endl;
	cout << "3.遍历" << endl;
	cout << "4.求树高、结点数、度为1结点数、叶子数" << endl;
	cout << "0.退出" << endl;
	while (cin >> t)
	{
		if (t == 0)
			break;
		switch (t)
		{
		case 1:
		{
			int c;
			cout << "输入数据:";
			cin >> c;
			Insert(&root, c);
			break;
		}
		case 2:
		{
			int c;
			cout << "输入数据:";
			cin >> c;
			Delete(&root, c);
			break;
		}
		case 3:
		{
			cout << "遍历结果:" << endl;
			InOderTraverse(root);
			cout << endl;
			break;
		}
		case 4:
		{
			cout << "树高:" << height(root) << endl;
			cout << "树节点数:" << count(root) << endl;
			cout << "度为1的结点数:" << leaf_1(root) << endl;
			cout << "叶子结点数:" << leaves(root) << endl;
			break;
		}
		}
	}
}

//二叉树菜单
void menu1(BiTree &tree)
{
	int t;
	cout << "*********************************************" << endl;
	cout << "***************菜单**************************" << endl;
	cout << "************1.中序遍历************************" << endl;
	cout << "************2.先序遍历************************" << endl;
	cout << "************3.后序遍历************************" << endl;
	cout << "************4.层次遍历************************" << endl;
	cout << "************5.求树高、结点数、度为1结点数、叶子数" << endl;
	cout << "************6.交换左右子树*********************" << endl;
	cout << "************0.返回****************************" << endl;
	cout << "**********************************************" << endl;
	
	cout << "请输入你想要的操作:";
	while (cin >> t)
	{
		if (t == 0)
			break;
		switch (t)
		{
		case 1:
		{InTraverse(tree);
		break; }
		case 2:
		{preorderTraverse(tree);
		break; }
		case 3:
		{postorderTraverse(tree);
		break; }
		case 4:
		{
			BinaryTreeLevelOrder(tree);
			break;
		}
		case 5:
		{
			cout << "树高:" << height(tree) << endl;
			cout << "树节点数:" << count(tree) << endl;
			cout << "度为1的结点数:" << leaf_1(tree) << endl;
			cout << "叶子结点数:" << leaves(tree) << endl;
			break;
		}
		case 6:
		{
			exchange(tree);
			break;
		}
		}
		cout << "请输入你想要的操作:";
	}
}

void main_menu(BiTree tree)
{
	int t;
	cout << "*********************************************" << endl;
	cout << "***************菜单**************************" << endl;
	cout << "************1.先序遍历创建二叉树**************" << endl;
	cout << "************2.二叉排序树插入删除**************" << endl;
	cout << "************0.退出***************************" << endl;
	cout << "*********************************************" << endl;
	cin >> t;
			switch (t)
			{
			case 0:
				break;
			case 1:
			{
				create_bitree(tree);
				
				menu1(tree);
				break;
			}
			case 2:
			{
				test();
				break;
			}
			}
}

int main()
{
	BiTree tree = NULL;
	main_menu(tree);
	return 0;
}

运行2结果:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值