(若有错误,敬请指正,谢谢!)
二叉排序树是什么?————> 二叉排序树
一个待排序数组中,第一个数据元素作为根节点,然后处理数组中后序的每一个元素,生成二叉树;对于之后的每一个元素我们都可以用插入的方式进行生成,相当于在一棵只有根节点的树上不断的进行插入操作,直到生成我们所需的二叉排序树;
那么对于插入算法来说,我们首先需要找到目前数据元素所需插入节点的地方,通过二叉排序树的节点大小关系(右孩子>根节点>左孩子)我们来定位待插入元素的位置。一般来说,查找也是做得这个工作,只不过插入操作在定位的基础上还需要进行数据的写入;
最后删除操作有点麻烦,因为我们删除节点后,对剩下的二叉排序树,我们需要更新成一个新的二叉排序树。对于删除的节点我们可以分成三个类型,叶子节点(直接删除)、单侧孩子节点(删除后,还需要把其孩子节点接上)、双侧孩子节点(找到顶替删除节点位置的节点,并处理该节点的孩子);
叶子节点:直接删除,不用考虑后序因素,我们可以直接把前驱节点的左孩子或右孩子置空,删除叶子节点;(至于直接删除叶子节点,不去管前驱节点的左右孩子,没有详细的实验)
单侧孩子节点:同样是利用前驱节点处理,该节点后面的孩子占据该节点的位置;
双侧孩子节点:可以有两种替换方式,一种是查询该节点右子树中最小的元素顶替该节点,一种是查询该节点左子树中最大的元素顶替该节点;这两种实质上都是一样的,都需要处理替换节点的孩子,当然显而易见,该替换节点只可能最多一侧有子树,这是一个比较好的消息。我们首先需要找到该替换节点,也需确定其前驱节点,处理时还需要处理替换节点子树的连接;
生成:
1 BiTree CreateBiT(int * array0, int n0) { // 生成
2 BiTree BT = NULL;
3 int i = 0;
4 while (i < n0) {
5 InsertBiT(BT, array0[i]);
6 i++;
7 }
8 return BT;
9 }
插入:
1 bool InsertBiT(BiTree & root, int k) { // 插入
2 if (root == NULL) { // 假设数据中不存在相同数据
3 root = (BiTree)malloc(sizeof(BiTNode));
4 root->key = k;
5 root->lchild = root->rchild = NULL;
6 return true;
7 }
8 else if (k < root->key)
9 return InsertBiT(root->lchild, k);
10 else
11 return InsertBiT(root->rchild, k);
12 }
查找:(查找算法可能存在一点问题)
1 int SearchBiT(BiTree root, int data, BiTree &temp) { // 查找
2 if (root == NULL || root->key == data) {
3 temp = root;
4 return 1;
5 } // 存在非任意值都有返回值问题
6 if (data < root->key)
7 SearchBiT(root->lchild, data, temp);
8 else
9 SearchBiT(root->rchild, data, temp);
10 }
删除:
叶子节点:
1 if (p->rchild == NULL && p->lchild == NULL) { // 叶子节点
2 if (temp->lchild == p)
3 temp->lchild = NULL;
4 else
5 temp->rchild = NULL;
6 }
单侧子树节点:
1 if (p->lchild == NULL) { // *p节点左子树空判断
2 if (root == p)
3 root = p->rchild;
4 else if (temp->lchild == p)
5 temp->lchild = p->rchild;
6 else
7 temp->rchild = p->rchild;
8 }
9 else if (p->rchild == NULL) { // *p节点右子树空判断
10 if (root == p)
11 root = p->lchild;
12 else if (temp->rchild == p)
13 temp->lchild = p->lchild;
14 else
15 temp->rchild = p->lchild;
16 }
双侧子树节点:
1 BiTree s, par;
2 s = p->rchild;
3 par = p;
4 while (s->lchild != NULL) {
5 par = s;
6 s = s->lchild;
7 }
8 p->key = s->key;
9 if (p->rchild->lchild == NULL)
10 p->rchild = s->rchild;
11 else
12 par->lchild = s->rchild;
13 free(s);
现在又有很多问题需要我们解决了;
那么假设只有一个元素,我们如何删除?
对于没有前驱节点的节点我们该怎么删除?
为什么双侧子树节点在查找替换节点之后,需要判断 p->rchild->lchild == NULL ?
不利用前驱节点,直接写 p = p->rchild / lchild 可行吗?
全部解决之后,想必二叉排序树也就迎刃而解了;
附:

1 #include<iostream> 2 #include<cstdlib> 3 4 using namespace std; 5 6 typedef struct BiTNode {// 结点结构 7 int key; // 关键字 8 struct BiTNode *lchild, *rchild; // 左右孩子指针 9 } BiTNode, *BiTree; 10 11 bool InsertBiT(BiTree & root, int k) { // 插入 12 if (root == NULL) { // 假设数据中不存在相同数据 13 root = (BiTree)malloc(sizeof(BiTNode)); 14 root->key = k; 15 root->lchild = root->rchild = NULL; 16 return true; 17 } 18 else if (k < root->key) 19 return InsertBiT(root->lchild, k); 20 else 21 return InsertBiT(root->rchild, k); 22 } 23 24 BiTree CreateBiT(int * array0, int n0) { // 生成 25 BiTree BT = NULL; 26 int i = 0; 27 while (i < n0) { 28 InsertBiT(BT, array0[i]); 29 i++; 30 } 31 return BT; 32 } 33 34 int SearchBiT(BiTree root, int data, BiTree &temp) { // 查找 35 if (root == NULL || root->key == data) { 36 temp = root; 37 return 1; 38 } // 存在非任意值都有返回值问题 39 if (data < root->key) 40 SearchBiT(root->lchild, data, temp); 41 else 42 SearchBiT(root->rchild, data, temp); 43 } 44 45 bool DeleteBiT(BiTree & root, int data) { // 删除 46 BiTree p, temp = root, *q = new BiTree; 47 cout << "*****检测删除数据是否存在*****" << endl; 48 SearchBiT(root, data, p); 49 if (p == NULL) { 50 cout << "不存在该数据,error!" << endl; 51 return false; 52 } 53 else 54 cout << "查找成功,数据存在" << endl; 55 while (temp->rchild != p && temp->lchild != p) 56 if (temp->key < p->key) // 无赖之下,求出上一个节点 57 temp = temp->rchild; 58 else if (temp->key > p->key) 59 temp = temp->lchild; 60 else if (root->lchild == NULL && root->rchild == NULL) { 61 root = NULL; // 若判断到此处,表明数据只有一个,并且删除这个元素 62 return true; 63 } 64 else 65 break; 66 if (p->rchild == NULL && p->lchild == NULL) { // 叶子节点 67 if (temp->lchild == p) 68 temp->lchild = NULL; 69 else 70 temp->rchild = NULL; 71 } 72 else if (p->lchild == NULL) { // *p节点左子树空判断 73 if (root == p) 74 root = p->rchild; 75 else if (temp->lchild == p) 76 temp->lchild = p->rchild; 77 else 78 temp->rchild = p->rchild; 79 } 80 else if (p->rchild == NULL) { // *p节点右子树空判断 81 if (root == p) 82 root = p->lchild; 83 else if (temp->rchild == p) 84 temp->lchild = p->lchild; 85 else 86 temp->rchild = p->lchild; 87 } 88 else { // 左右子树都存在 89 BiTree s, par; 90 s = p->rchild; 91 par = p; 92 while (s->lchild != NULL) { 93 par = s; 94 s = s->lchild; 95 } 96 p->key = s->key; 97 if (p->rchild->lchild == NULL) 98 p->rchild = s->rchild; 99 else 100 par->lchild = s->rchild; 101 free(s); 102 } 103 return true; 104 } 105 106 void InOrder(BiTree Bt) { 107 if (Bt != NULL) { 108 InOrder(Bt->lchild); 109 cout << Bt->key << " "; 110 InOrder(Bt->rchild); 111 } 112 } 113 114 int main() 115 { 116 int i, n, v, k; 117 BiTree Bt, bt = NULL; 118 cout << "请输入待排数组序列个数,以及待排序列:"; 119 cin >> n; 120 int *array = new int[n]; 121 for (i = 0; i < n; i++) 122 cin >> array[i]; 123 Bt = CreateBiT(array, n); 124 cout << "--------------------" << endl << "请输入查找关键字:v = "; 125 cin >> v; 126 SearchBiT(Bt, v, bt); 127 if (bt == NULL) 128 cout << "不存在该关键字" << endl; 129 else 130 cout << "存在该关键字,v = " << bt->key << " 查找成功!" << endl; 131 cout << "--------------------" << endl << "请输入删除关键字:w = "; 132 cin >> v; 133 k = DeleteBiT(Bt, v); 134 if (k == 1) 135 cout << "删除成功!" << endl; 136 else 137 cout << "删除失败!" << endl; 138 cout << "--------------------" << endl << "二叉排序树输出:" << endl; 139 InOrder(Bt); 140 if (Bt == NULL) 141 cout << "数据已全部删除" << endl; 142 return 0; 143 }
2020-05-27