#include<stdio.h>
#include<stdlib.h>
#define ElemType int
//二叉排序树结点类型定义
typedef struct BSTNode {
ElemType data; //数据元素
struct BSTNode* lchild, * rchild; //左右指针
}BSTNode, * BSTree;
/*函数声明*/
BSTNode* BST_Search(BSTree T, ElemType key); //1-1.查找操作-非递归
BSTNode* BSTSearch(BSTree T, ElemType key); //1-2.查找操作-递归
bool BST_Insert(BSTree& T, ElemType key); //2-1.插入操作-非递归
bool BSTInsert(BSTree& T, ElemType key); //2-2.插入操作-递归
void Create_BST(BSTree& T, ElemType arr[], int n); //3.构造二叉排序树
BSTNode* FirstNode(BSTNode* p); //4-1.找到最左下结点
BSTNode* LastNode(BSTNode* p); //4-2.找到最右下结点
BSTNode* BST_Delete1(BSTree& T, ElemType key); //4-3.删除操作-用右子树中最左下结点填充
BSTNode* BST_Delete2(BSTree& T, ElemType key); //4-4.删除操作-用左子树中最右下结点填充
void InOrder(BSTree T); //5.中序遍历
//1-1.查找操作-非递归(最坏空间复杂度O(1))
BSTNode* BST_Search(BSTree T, ElemType key) {
while (T != NULL && key != T->data) { //若树空或找到结点,则结束循环
if (key < T->data)
T = T->lchild; //小于,在左子树上查找
else
T = T->rchild; //大于,在右子树上查找
}
return T;
}
//1-2.查找操作-递归(最坏空间复杂度O(h),h指树的高度)
BSTNode* BSTSearch(BSTree T, ElemType key) {
if (T == NULL)
return NULL; //查找失败
if (key == T->data)
return T; //查找成功
else if (key < T->data)
return BSTSearch(T->lchild, key); //小于,在左子树上查找
else
return BSTSearch(T->rchild, key); //大于,在右子树上查找
}
//2-1.插入操作-非递归(最坏空间复杂度O(1))
bool BST_Insert(BSTree& T, ElemType key) {
BSTNode* p = T; //搜索指针
BSTNode* parent = NULL; //p的双亲结点
while (p) { //找到插入位置
if (key == p->data) //树中存在相同关键字的结点
return false; //插入失败
else {
parent = p; //保留p的双亲结点
if (key < p->data)
p = p->lchild; //小于,在左子树上寻找插入位置
else
p = p->rchild; //大于,在右子树上寻找插入位置
}
}
/* 直接插入到p是不会改变二叉树的
p = (BSTNode*)malloc(sizeof(BSTNode)); //分配存储空间
p->data = key; //放入结点值
p->lchild = p->rchild = NULL; //左右孩子置空
*/
BSTNode* s = (BSTNode*)malloc(sizeof(BSTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if (!parent) //若T为空树
T = s; //将s设为根结点
else if (key < parent->data)
parent->lchild = s; //小于,插入pre的左子树
else
parent->rchild = s; //大于,插入pre的右子树
return true; //插入成功
}
//2-2.插入操作-递归(最坏空间复杂度O(h),h指树的高度)
bool BSTInsert(BSTree& T, ElemType key) {
if (T == NULL) { //找到要插入的位置
T = (BSTNode*)malloc(sizeof(BSTNode)); //分配存储空间
T->data = key; //放入结点值
T->lchild = T->rchild = NULL; //左右孩子置空
return true; //插入成功
}
else if (key == T->data) //树中存在相同关键字的结点
return false; //插入失败
else if (key < T->data)
return BSTInsert(T->lchild, key); //小于,在左子树上插入
else if (key > T->data)
return BSTInsert(T->rchild, key); //大于,在右子树上插入
}
/*3.构造二叉排序树:按照arr[]中的关键字序列建立二叉排序树*/
void Create_BST(BSTree& T, ElemType arr[], int n) {
T = NULL; //初始T为空树
int i = 0;
while (i < n) { //依次将每个关键字插入到二叉排序树中
BSTInsert(T, arr[i]);
i++;
}
}
//4-1.找到最左下结点,也是最小结点
BSTNode* FirstNode(BSTNode* p) {
if (p)
while (p->lchild)
p = p->lchild;
return p;
}
//4-2.找到最右下结点,也是最大结点
BSTNode* LastNode(BSTNode* p) {
if (p)
while (p->rchild)
p = p->rchild;
return p;
}
//4-3.删除操作-用右子树中最左下结点填充
BSTNode* BST_Delete1(BSTree& T, ElemType key) {
BSTNode* tmp;
if (!T)
printf("要删除的元素未找到!");
else if (key < T->data)
T->lchild = BST_Delete1(T->lchild, key); //小于,删除左孩子
else if (key > T->data)
T->rchild = BST_Delete1(T->rchild, key); //大于,删除右孩子
else //找到要删除的结点
if (T->lchild && T->rchild) { //1.被删除结点右左右两个子结点
tmp = FirstNode(T->rchild); //找到右子树的最左下结点填充删除结点
T->data = tmp->data;
T->rchild = BST_Delete1(T->rchild, T->data); //在删除结点的右子树中删除最小结点
}
else { //2.被删除结点有一个子结点或者都没有
tmp = T;
if (!T->lchild)
T = T->rchild; //有右孩子或无子结点
else if (!T->rchild)
T = T->lchild;
free(tmp);
}
return T;
}
//4-4.删除操作-用左子树中最右下结点填充
BSTNode* BST_Delete2(BSTree& T, ElemType key) {
BSTNode* tmp;
if (!T)
printf("要删除的元素未找到!");
else if (key < T->data)
T->lchild = BST_Delete2(T->lchild, key);
else if (key > T->data)
T->rchild = BST_Delete2(T->rchild, key);
else //找到要删除的结点
if (T->lchild && T->rchild) { //1.被删除结点有左右两个子结点
tmp = LastNode(T->lchild); //找到左子树的最右下结点填充删除结点
T->data = tmp->data;
T->lchild = BST_Delete2(T->lchild, T->data); //在删除结点的左子树中删除最大结点
}
else { //2.被删除结点有一个子结点或者都没有
tmp = T;
if (!T->lchild)
T = T->rchild; //有右孩子或无子结点
else if (!T->rchild)
T = T->lchild;
free(tmp);
}
return T;
}
/*5.中序遍历:由二叉排序树的特性,对二叉排序树进行中序遍历会得到递增序列*/
void InOrder(BSTree T) {
if (T != NULL) {
InOrder(T->lchild); //递归遍历左子树
printf("%d\t", T->data); //访问根结点
InOrder(T->rchild); //递归遍历右子树
}
}
int main() {
BSTree T; //声明一棵二叉排序树
int arr[] = { 19,13,11,8,50,26,21,30,66,60,70,63,61,65 }; //测试序列
/*1、构造一棵二叉排序树*/
Create_BST(T, arr, 14);
printf("<————————构造二叉排序树————————>\n");
InOrder(T);
/*2、插入指定元素-递归*/
printf("\n<————————二叉排序树递归插入元素————————>\n");
if (BSTInsert(T, 62))
InOrder(T);
else
printf("树中已存在相同结点,插入失败!");
/*3、插入指定元素-非递归*/
printf("\n<————————二叉排序树非递归插入元素————————>\n");
if(BST_Insert(T, 67))
InOrder(T);
else
printf("树中已存在相同结点,插入失败!");
/*4、删除指定元素-右子树最左下结点填充*/
printf("\n<————————删除指定元素-右子树最左下结点填充————————>\n");
BST_Delete1(T, 60);
InOrder(T);
/*5、删除指定元素-左子树最右下结点填充*/
printf("\n<————————删除指定元素-左子树最右下结点填充————————>\n");
BST_Insert(T, 60); //先恢复被删除的测试结点,便于对比
BST_Delete2(T, 60);
InOrder(T);
return 0;
}
平衡二叉树–>掌握其四种旋转:LL,RR,LR,RL。
哈夫曼树---->掌握其构造方法和哈夫曼编码。
这两个应用主要在于理解其思想。