二叉树用二叉链表表示 (独立完成)
设计内容:
(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结果: