动态查找表之二叉搜索树
生活随笔
收集整理的這篇文章主要介紹了
动态查找表之二叉搜索树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、二叉搜索樹(BST)
二叉搜索樹(二叉排序樹)定義如下:
(1)一棵空樹;
(2)或者不是空樹:
? ? ? ? ?1)若左子樹不空,則左子樹上所有結點的值均小于它的根結點的值;
? ? ? ? ?2)若右子樹不空,則右子樹上所有結點的值均大于它的根結點的值;
? ? ? ? ?3)左、右子樹也分別為二叉排序樹。
?
二、二叉搜索的操作
/************************************************************************* 這是一個二叉查找樹,實現了以下操作:插入結點、構造二叉樹、刪除結點、查找、 查找最大值、查找最小值、查找指定結點的前驅和后繼。上述所有操作時間復雜度 均為o(h),其中h是樹的高度 注釋很詳細,具體內容就看代碼吧 *************************************************************************/#include<stdio.h> #include<stdlib.h> //二叉查找樹結點描述 typedef int KeyType; typedef struct Node {KeyType key; //關鍵字 struct Node * left; //左孩子指針 struct Node * right; //右孩子指針 struct Node * parent; //指向父節點指針 }Node, *PNode;//往二叉查找樹中插入結點 //插入的話,可能要改變根結點的地址,所以傳的是二級指針 void inseart(PNode * root, KeyType key) {//初始化插入結點 PNode p = (PNode)malloc(sizeof(Node));p->key = key;p->left = p->right = p->parent = NULL;//空樹時,直接作為根結點 if ((*root) == NULL) {*root = p;return;}//插入到當前結點(*root)的左孩子 if ((*root)->left == NULL && (*root)->key > key) {p->parent = (*root);(*root)->left = p;return;}//插入到當前結點(*root)的右孩子 if ((*root)->right == NULL && (*root)->key < key) {p->parent = (*root);(*root)->right = p;return;}if ((*root)->key > key)inseart(&(*root)->left, key);else if ((*root)->key < key)inseart(&(*root)->right, key);elsereturn; }//查找元素,找到返回關鍵字的結點指針,沒找到返回NULL PNode search(PNode root, KeyType key) {if (root == NULL)return NULL;if (key > root->key) //查找右子樹 return search(root->right, key);else if (key < root->key) //查找左子樹 return search(root->left, key);elsereturn root; }//查找最小關鍵字,空樹時返回NULL PNode searchMin(PNode root) {if (root == NULL)return NULL;if (root->left == NULL)return root;else //一直往左孩子找,直到沒有左孩子的結點 return searchMin(root->left); }//查找最大關鍵字,空樹時返回NULL PNode searchMax(PNode root) {if (root == NULL)return NULL;if (root->right == NULL)return root;else //一直往右孩子找,直到沒有右孩子的結點 return searchMax(root->right); }//查找某個結點的前驅 PNode searchPredecessor(PNode p) {//空樹 if (p == NULL)return p;//有左子樹、左子樹中最大的那個 if (p->left)return searchMax(p->left);//無左子樹,查找某個結點的右子樹遍歷完了 else {if (p->parent == NULL)return NULL;//向上尋找前驅 while (p) {if (p->parent->right == p)break;p = p->parent;}return p->parent;} }//查找某個結點的后繼 PNode searchSuccessor(PNode p) {//空樹 if (p == NULL)return p;//有右子樹、右子樹中最小的那個 if (p->right)return searchMin(p->right);//無右子樹,查找某個結點的左子樹遍歷完了 else {if (p->parent == NULL)return NULL;//向上尋找后繼 while (p) {if (p->parent->left == p)break;p = p->parent;}return p->parent;} }//根據關鍵字刪除某個結點,刪除成功返回1,否則返回0 //如果把根結點刪掉,那么要改變根結點的地址,所以傳二級指針 int deleteNode(PNode* root, KeyType key) {PNode q;//查找到要刪除的結點 PNode p = search(*root, key);KeyType temp; //暫存后繼結點的值 //沒查到此關鍵字 if (!p)return 0;//1.被刪結點是葉子結點,直接刪除 if (p->left == NULL && p->right == NULL) {//只有一個元素,刪完之后變成一顆空樹 if (p->parent == NULL) {free(p);(*root) = NULL;}else {//刪除的結點是父節點的左孩子 if (p->parent->left == p)p->parent->left = NULL;else //刪除的結點是父節點的右孩子 p->parent->right = NULL;free(p);}}//2.被刪結點只有左子樹 else if (p->left && !(p->right)) {p->left->parent = p->parent;//如果刪除是父結點,要改變父節點指針 if (p->parent == NULL)*root = p->left;//刪除的結點是父節點的左孩子 else if (p->parent->left == p)p->parent->left = p->left;else //刪除的結點是父節點的右孩子 p->parent->right = p->left;free(p);}//3.被刪結點只有右孩子 else if (p->right && !(p->left)) {p->right->parent = p->parent;//如果刪除是父結點,要改變父節點指針 if (p->parent == NULL)*root = p->right;//刪除的結點是父節點的左孩子 else if (p->parent->left == p)p->parent->left = p->right;else //刪除的結點是父節點的右孩子 p->parent->right = p->right;free(p);}//4.被刪除的結點既有左孩子,又有右孩子 //該結點的后繼結點肯定無左子樹(參考上面查找后繼結點函數) //刪掉后繼結點,后繼結點的值代替該結點 else {//找到要刪除結點的后繼 q = searchSuccessor(p);temp = q->key;//刪除后繼結點 deleteNode(root, q->key);p->key = temp;}return 1; }//創建一棵二叉查找樹 void create(PNode* root, KeyType *keyArray, int length) {int i;//逐個結點插入二叉樹中 for (i = 0; i<length; i++)inseart(root, keyArray[i]); }int main(void) {int i;PNode root = NULL;KeyType nodeArray[11] = { 15,6,18,3,7,17,20,2,4,13,9 };create(&root, nodeArray, 11);for (i = 0; i<2; i++)deleteNode(&root, nodeArray[i]);printf("%d\n", searchPredecessor(root)->key);printf("%d\n", searchSuccessor(root)->key);printf("%d\n", searchMin(root)->key);printf("%d\n", searchMax(root)->key);printf("%d\n", search(root, 13)->key);return 0; }總結
以上是生活随笔為你收集整理的动态查找表之二叉搜索树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【工具使用】apizza和postman
- 下一篇: 微软雅黑的问题(for silverli