数据结构(8-3)二叉排序树(查找、插入删除)
目錄
一、基礎理論
1、特點:?
2、結構:?
二、查找
三、插入
四、刪除
1、被刪除的結點D是葉子結點
2、被刪除的結點D僅有一個孩子
2-1、刪除結點14(有左無右)
2-2、刪除結點?10?(有右無左)
3、被刪除結點的左右孩子都存在
方法一:以左子樹最大結點替換根結點
方法二:以右子樹最小結點替換根結點
總代碼
參考資料
一、基礎理論
1、特點:?
(1) 若它的左子樹不空,則?左子樹?上所有結點的值?均小于?它的根結點的值;
(2) 若它的右子樹不空,則?右子樹?上所有結點的值?均大于?它的根結點的值;
(3) 它的?左、右子樹又分別為二叉排序樹?。
2、結構:?
二叉樹
?
?
二、查找
(1)從根開始,未找到,則獲取空結點地址,返回;
(2)相等則找到,提示,退出;
(3)key < 結點,向左遍歷(遞歸lchild)
(4)key > 結點,向右遍歷(遞歸rchild)
(查找的同時還可以進行定位,最后返回需要查找的位置)
(和二分查找比較相似)
查找結點13:
第一步:訪問根結點?8?.
第二步:根據二叉排序樹的左子樹均比根結點小,右子樹均比根結點大的性質,?13 > 8?,因此值為13的結點可能在根結點 8 的右子樹當中,我們查看根結點的右子節點?10?:
第三步:與第二步相似,?13 > 10?,因此查看結點?10?的右孩子?14?:
第四步:根據二叉排序樹的左子樹均比根結點小,右子樹均比根結點大的性質,?13 < 14?,因此查看?14?的左孩子 ?13?,發現剛好和要查找的值相等:
//查找二叉排序樹
void Search_BST(pBiTree* T, int key) //關鍵字
{//查找失敗(沒有值,需要添加)if (!(*T)){p = T;return;}//查找成功if (key == (*T)->data){printf("查找成功!\n");success = 1;return;}else if (key < (*T)->data)Search_BST(&((*T)->lchild), key); //小,往左遍歷elseSearch_BST(&((*T)->rchild), key); //大,往右遍歷
}
三、插入
先查找,定位到待插入的位置,直接進行插入。?
首結點放入根,后面的依次與前面的每一個結點判斷,小則放在左邊,大則放在右邊。
插入全部:
?代碼
//插入二叉排序樹
void Insert_BST(int key) //索引
{Search_BST(&head, key);//找到if (success)return;//未找到(創建新結點,容納)(*p) = (pBiTree)malloc(sizeof(pBiTree));(*p)->data = key; //存儲//給左右子樹賦空值(*p)->lchild = NULL;(*p)->rchild = NULL;
}
四、刪除
刪除操作與查找和插入操作不同,我們要分以下三種情況進行處理:
1、被刪除的結點D是葉子結點
從二叉排序樹當中直接刪除即可,也不會影響樹的結構。
2、被刪除的結點D僅有一個孩子
(1)如果只有左孩子,沒有右孩子,那么只需要把要刪除結點的左孩子鏈接到要刪除結點的父親節點,然后刪除D結點就好了;(覆蓋)
(2)如果只有右孩子,沒有左孩子,那么只要將要刪除結點D的右孩子重接到要刪除結點D的父親結點。(覆蓋)
2-1、刪除結點14(有左無右)
覆蓋。
保存要刪除結點?14?的?左孩子?結點?13?到臨時變量 temp,并刪除結點?14;
將刪除結點?14?的父結點?10?的?右孩子?設置為 temp,即結點?13。
2-2、刪除結點?10?(有右無左)
覆蓋。
保存要刪除結點?10?的?右孩子?結點?14?到臨時變量 temp,并刪除結點?10;
將刪除結點?10?的父結點?8?的?右孩子?設置為 temp,即結點?14。
3、被刪除結點的左右孩子都存在
用左子樹中的最大值或者右子樹中的最小值替換頂點。
(對于這種情況就復雜一些了,這一次我們將圖變得復雜一點兒,給原來結點?10?增加了一個左孩子結點?9?。)
對于上面的二叉排序樹的中序遍歷結果如下所示:
以刪除頂點8為例:?
方法一:以左子樹最大結點替換根結點
(1)獲取左子樹中的最大結點7
(2)將刪除結點?8?的值替換為?7?
(3)刪除根結點左子樹當中值最大結點(要考慮好該結點有無左孩子)
方法二:以右子樹最小結點替換根結點
(1)查找刪除結點?8?的右子樹當中值最小的結點,即?9?
(2)將刪除結點?8?的值替換為?9?
(3)刪除根結點右子樹當中值最小的結點(要考慮好該結點有無右孩子)
代碼1:定位到待刪除的結點
//刪除(定位到刪除的結點)
void Delete_BST(pBiTree* p, int key)
{if (*p) //結點存在{if (key == (*p)->data)Delete(p);else if (key < (*p)->data)Delete_BST(&(*p)->lchild, key); //遞歸左elseDelete_BST(&(*p)->rchild, key); //遞歸右}
}
代碼2:單結點刪除
//刪除結點
void Delete(pBiTree* p)
{pBiTree s;//1、左右均為空if (!(*p)->lchild && !(*p)->rchild)*p = NULL;//2、左子樹為空else if (!(*p)->lchild)*p = (*p)->rchild; //覆蓋//3、右子樹為空else if (!(*p)->rchild)*p = (*p)->lchild; //覆蓋//4、左右子樹均不為空(兩個方法:找左子樹最大值/找右子樹最小值)//這里選擇找左子樹最大值else{pBiTree q = (*p);s = (*p)->lchild; //先定位左子樹while (s->rchild){q = s; //保存上一結點s = s->rchild; //往后找}(*p)->data = s->data; //覆蓋//考慮:存在左結點p = &q; //定位到上一節點(*p)->rchild = s->lchild; //重接q右子樹}
}
總代碼
//二叉排序樹(查找,插入,刪除)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>#define MAXSIZE 20
int data[MAXSIZE];
int length = 0; //數組長度
int success = 0; //記錄是否查找成功//二叉樹結構體
typedef struct BiTree
{int data;struct BiTree* lchild, * rchild;
}BiTree, * pBiTree, ** p2BiTree;
BiTree* head;
pBiTree* p;//輸入數據
void Input()
{int Data;int i = 0;printf("請輸入初始數據:\t");//輸入數據do{scanf("%d", &Data);data[i++] = Data;} while (getchar() != '\n');length = i; //記錄數組長度
}//二叉樹初始化
void Init_BiTree()
{head = NULL;
}//查找二叉排序樹
void Search_BST(pBiTree* T, int key) //關鍵字
{success = 0; //初始化,不影響查找結果//查找失敗(沒有值,需要添加)if (!(*T)){p = T;return;}//查找成功if (key == (*T)->data){printf("查找成功!\n");success = 1;return;}else if (key < (*T)->data)Search_BST(&((*T)->lchild), key); //小,往左遍歷elseSearch_BST(&((*T)->rchild), key); //大,往右遍歷
}//插入
void Insert_BST(int key) //索引
{Search_BST(&head, key);//找到if (success)return;//未找到(創建新結點,容納)(*p) = (pBiTree)malloc(sizeof(pBiTree));(*p)->data = key; //存儲//給左右子樹賦空值(*p)->lchild = NULL;(*p)->rchild = NULL;
}//刪除結點
void Delete(pBiTree* p)
{pBiTree s;//1、左右均為空if (!(*p)->lchild && !(*p)->rchild)*p = NULL;//2、左子樹為空else if (!(*p)->lchild)*p = (*p)->rchild; //覆蓋//3、右子樹為空else if (!(*p)->rchild)*p = (*p)->lchild; //覆蓋//4、左右子樹均不為空(兩個方法:找左子樹最大值/找右子樹最小值)//這里選擇找左子樹最大值else{pBiTree q = (*p);s = (*p)->lchild; //先定位左子樹while (s->rchild){q = s; //保存上一結點s = s->rchild; //往后找}(*p)->data = s->data; //覆蓋//考慮:存在左結點p = &q; //定位到上一節點(*p)->rchild = s->lchild; //重接q右子樹}
}//刪除(定位到刪除的結點)
void Delete_BST(pBiTree* p, int key)
{if (*p) //結點存在{if (key == (*p)->data)Delete(p);else if (key < (*p)->data)Delete_BST(&(*p)->lchild, key); //遞歸左elseDelete_BST(&(*p)->rchild, key); //遞歸右}
}//中序遍歷輸出
void Inorder_Traverse(pBiTree p)
{if (p){Inorder_Traverse(p->lchild);printf("%d ", p->data);Inorder_Traverse(p->rchild);}
}int main()
{int key;Input(); //輸入Init_BiTree(); //二叉樹初始化for (int i = 0; i < length; i++)Insert_BST(data[i]); //插入二叉排序樹//刪除printf("\n請輸入需要刪除的數據:\t");scanf("%d", &key);Delete_BST(&head, key);//查找printf("請輸入需要查詢的數據:\t");scanf("%d", &key);Search_BST(&head, key);//插入printf("\n請輸入需要插入的數據:\t");scanf("%d", &key);Insert_BST(key);//查找Search_BST(&head, key);Inorder_Traverse(head); //遍歷(中序遍歷,從小到大輸出)return 0;
}
參考資料
https://blog.csdn.net/kexuanxiu1163/article/details/106168677?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162884083916780271545792%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162884083916780271545792&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-106168677.ecpm_v1_rank_v29&utm_term=%E4%BA%8C%E5%8F%89%E6%8E%92%E5%BA%8F%E6%A0%91&spm=1018.2226.3001.4187
總結
以上是生活随笔為你收集整理的数据结构(8-3)二叉排序树(查找、插入删除)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言结束输入(两种方法)
- 下一篇: OpenCV(十五)边缘检测1 -- S