数据结构-二叉排序树操作实践
数据结构-二叉排序树操作实践
编写函数,建立有序表,利用二叉排序树的插入算法建立二叉排序树
#include<iostream>
#include<malloc.h>
using namespace std;
#define MAXSIZE 50
// 定义二叉树的结点
typedef struct BiTNode {
int data;
struct BiTNode* lChild, * rChild;
}BiTNode, *BiTree;
/** * 在二叉排序树T中插入一个关键字为k的结点 * @param T 二叉排序树T * @param k 要插入的关键字k * @return 成功返回真,否则为假 */
bool BST_Insert(BiTree& T, int k) {
if (T == NULL) {
// 原数为空,新插入的记录为根结点
T = (BiTree)malloc(sizeof(BiTNode));
if (T) {
T->data = k;
T->lChild = T->rChild = NULL;
return true; // 成功
}
}
else if (k == T->data) // 树中存在相同关键字的结点
return false;
else if (k < T->data) // 插入T的左子树
return BST_Insert(T->lChild, k);
else // 插入T的右子树
return BST_Insert(T->rChild, k);
}
/** * 用关键字数组构造二叉排序树 * @param T 二叉排序树T * @param keys 关键字数组 * @param n 关键字数组的元素个数 */
void Creat_BST(BiTree& T, int keys[], int n) {
T = NULL; // 初始化为空树
int i = 0;
while (i < n) {
// 将为每个元素依次插入
BST_Insert(T, keys[i]);
i++;
}
}
/** * 先序遍历二叉排序树 * @param T 二叉排序树T */
void PreOrder_BST(BiTree T) {
if (T != NULL) {
cout << T->data << " ";
PreOrder_BST(T->lChild);
PreOrder_BST(T->rChild);
}
}
/** * 中序遍历二叉排序树 * @param T 二叉排序树T */
void InOrder_BST(BiTree T) {
if (T != NULL) {
InOrder_BST(T->lChild);
cout << T->data << " ";
InOrder_BST(T->rChild);
}
}
/** * 后序遍历二叉排序树 * @param T 二叉排序树T */
void PostOrder_BST(BiTree T) {
if (T != NULL) {
PostOrder_BST(T->lChild);
PostOrder_BST(T->rChild);
cout << T->data << " ";
}
}
int main() {
int n;
cin >> n;
int keys[MAXSIZE];
for (int i = 0; i < n; i++)
cin >> keys[i];
BiTree T;
Creat_BST(T, keys, n);
cout << "先序遍历:";
PreOrder_BST(T);
cout << endl;
cout << "中序遍历:";
InOrder_BST(T);
cout << endl;
cout << "后序遍历:";
PostOrder_BST(T);
cout << endl;
return 0;
}
注:
- 二叉排序树中默认没有相同的元素
- 输入的顺序是随意的,自己可以手动的根据输入的顺序构造二叉排序树,再对该二叉排序树进行先、中、后序遍历,跟输出的遍历结果对照,即可判断程序所构造的二叉排序树是否正确。
在以上二叉排序树中删除某一指定关键字元素
/** * 从二叉排序树中删除结点p,并重接它的左或右子树 * @param p 要删除的结点 * @return 成功为真 */
bool Delete(BiTree& p) {
BiTree q, s;
if (!p->rChild) {
// 右子树为空,则只需要重接它的左子树
q = p;
p = p->lChild;
free(q);
}
else if (!p->lChild) {
// 左子树为空,则只需要重接它的右子树
q = p;
p = p->rChild;
free(q);
}
else {
// 左右子树均不为空
q = p;
s = p->lChild;
while (s->rChild) {
// 转左,然后向右到尽头
q = s;
s = s->rChild;
}
p->data = s->data; // s指向被删结点的前驱
if (q != p) // 重接*q的右子树
q->rChild = s->lChild;
else // 重接*q的左子树
q->lChild = s->rChild;
free(s);
}
return true;
}
/** * 在二叉排序树中删除关键字等于key的结点 * @param T 二叉排序树T * @param key 要删除的关键字元素 * @return 成功返回真,否则返回假 */
bool DeleteBST(BiTree& T, int key) {
if (!T) // T为空
return false;
else
{
if (key == T->data) //找到关键字等于key的数据元素
return Delete(T);
else if (key < T->data)
return DeleteBST(T->lChild, key);
else
return DeleteBST(T->rChild, key);
}
}
int key;
cin >> key;
DeleteBST(T, key);
cout << "------删除" << key << "------" << endl;
cout << "先序遍历:";
PreOrder_BST(T);
cout << endl;
cout << "中序遍历:";
InOrder_BST(T);
cout << endl;
cout << "后序遍历:";
PostOrder_BST(T);
cout << endl;
注:
- 二叉排序树中默认没有相同的元素
- 输入的顺序是随意的,自己可以手动的根据输入的顺序构造二叉排序树,再对该二叉排序树进行先、中、后序遍历,跟输出的遍历结果对照,即可判断程序所构造的二叉排序树是否正确。
- 在二叉排序树中删除元素是一件比较麻烦的事,根据不同的情况,在删除后要对树进行不同的调整。
采用折半查找实现某一已知的关键字的查找(采用顺序表存储结构)
这里继续基于上面的程序来写,显然,二叉排序树的中序遍历即为一个递增的顺序。我们利用中序遍历来构造一个顺序表,再进行折半查找操作
int SeqT[MAXSIZE]; // 定义一个顺序表,用于折半查找
int t=0;
/** * 中序遍历二叉排序树 * @param T 二叉排序树T */
void InOrder_BST(BiTree T) {
if (T != NULL) {
InOrder_BST(T->lChild);
cout << T->data << " ";
SeqT[t++] = T->data; // 按中序遍历的方式遍历二叉排序树即可得到一组有序的数
InOrder_BST(T->rChild);
}
}
/** * 折半查找 * @param SeqT 有序表 * @param n 有序表中元素个数 * @param key 待查找的关键字 * @return 该关键字在表中的位置(第几个),否则返回0 */
int Search_Bin(int SeqT[], int n, int key) {
int low = 0;
int high = n - 1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (key == SeqT[mid]) // 找到待查元素
return mid + 1;
else if (key < SeqT[mid]) // 继续在前半区间查找
high = mid - 1;
else // 继续在后半区间查找
low = mid + 1;
}
return 0; // 有序表中不存在待查元素
}
int key2;
cin >> key2;
cout << key2 << "在表中第" << Search_Bin(SeqT, n, key2) << "个位置";
完成程序代码
#include<iostream>
#include<malloc.h>
using namespace std;
#define MAXSIZE 50
int SeqT[MAXSIZE]; // 定义一个顺序表,用于折半查找
int t=0;
// 定义二叉树的结点
typedef struct BiTNode {
int data;
struct BiTNode* lChild, * rChild;
}BiTNode, *BiTree;
/** * 在二叉排序树T中插入一个关键字为k的结点 * @param T 二叉排序树T * @param k 要插入的关键字k * @return 成功返回真,否则为假 */
bool BST_Insert(BiTree& T, int k) {
if (T == NULL) {
// 原数为空,新插入的记录为根结点
T = (BiTree)malloc(sizeof(BiTNode));
if (T) {
T->data = k;
T->lChild = T->rChild = NULL;
return true; // 成功
}
}
else if (k == T->data) // 树中存在相同关键字的结点
return false;
else if (k < T->data) // 插入T的左子树
return BST_Insert(T->lChild, k);
else // 插入T的右子树
return BST_Insert(T->rChild, k);
}
/** * 用关键字数组构造二叉排序树 * @param T 二叉排序树T * @param keys 关键字数组 * @param n 关键字数组的元素个数 */
void Creat_BST(BiTree& T, int keys[], int n) {
T = NULL; // 初始化为空树
int i = 0;
while (i < n) {
// 将为每个元素依次插入
BST_Insert(T, keys[i]);
i++;
}
}
/** * 先序遍历二叉排序树 * @param T 二叉排序树T */
void PreOrder_BST(BiTree T) {
if (T != NULL) {
cout << T->data << " ";
PreOrder_BST(T->lChild);
PreOrder_BST(T->rChild);
}
}
/** * 中序遍历二叉排序树 * @param T 二叉排序树T */
void InOrder_BST(BiTree T) {
if (T != NULL) {
InOrder_BST(T->lChild);
cout << T->data << " ";
SeqT[t++] = T->data; // 按中序遍历的方式遍历二叉排序树即可得到一组有序的数
InOrder_BST(T->rChild);
}
}
/** * 后序遍历二叉排序树 * @param T 二叉排序树T */
void PostOrder_BST(BiTree T) {
if (T != NULL) {
PostOrder_BST(T->lChild);
PostOrder_BST(T->rChild);
cout << T->data << " ";
}
}
/** * 从二叉排序树中删除结点p,并重接它的左或右子树 * @param p 要删除的结点 * @return 成功为真 */
bool Delete(BiTree& p) {
BiTree q, s;
if (!p->rChild) {
// 右子树为空,则只需要重接它的左子树
q = p;
p = p->lChild;
free(q);
}
else if (!p->lChild) {
// 左子树为空,则只需要重接它的右子树
q = p;
p = p->rChild;
free(q);
}
else {
// 左右子树均不为空
q = p;
s = p->lChild;
while (s->rChild) {
// 转左,然后向右到尽头
q = s;
s = s->rChild;
}
p->data = s->data; // s指向被删结点的前驱
if (q != p) // 重接*q的右子树
q->rChild = s->lChild;
else // 重接*q的左子树
q->lChild = s->rChild;
free(s);
}
return true;
}
/** * 在二叉排序树中删除关键字等于key的结点 * @param T 二叉排序树T * @param key 要删除的关键字元素 * @return 成功返回真,否则返回假 */
bool DeleteBST(BiTree& T, int key) {
if (!T) // T为空
return false;
else
{
if (key == T->data) //找到关键字等于key的数据元素
return Delete(T);
else if (key < T->data)
return DeleteBST(T->lChild, key);
else
return DeleteBST(T->rChild, key);
}
}
/** * 折半查找 * @param SeqT 有序表 * @param n 有序表中元素个数 * @param key 待查找的关键字 * @return 该关键字在表中的位置(第几个),否则返回0 */
int Search_Bin(int SeqT[], int n, int key) {
int low = 0;
int high = n - 1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (key == SeqT[mid]) // 找到待查元素
return mid + 1;
else if (key < SeqT[mid]) // 继续在前半区间查找
high = mid - 1;
else // 继续在后半区间查找
low = mid + 1;
}
return 0; // 有序表中不存在待查元素
}
int main() {
int n;
cin >> n;
int keys[MAXSIZE];
for (int i = 0; i < n; i++)
cin >> keys[i];
BiTree T;
Creat_BST(T, keys, n);
cout << "先序遍历:";
PreOrder_BST(T);
cout << endl;
cout << "中序遍历:";
InOrder_BST(T);
cout << endl;
cout << "后序遍历:";
PostOrder_BST(T);
cout << endl;
int key;
cin >> key;
DeleteBST(T, key);
cout << "------删除" << key << "------" << endl;
cout << "先序遍历:";
PreOrder_BST(T);
cout << endl;
cout << "中序遍历:";
InOrder_BST(T);
cout << endl;
cout << "后序遍历:";
PostOrder_BST(T);
cout << endl;
int key2;
cin >> key2;
cout << key2 << "在表中第" << Search_Bin(SeqT, n, key2) << "个位置";
return 0;
}
创作不易,喜欢的话加个关注点个赞,谢谢谢谢谢!