生活随笔
收集整理的這篇文章主要介紹了
重学数据结构007——二叉查找树
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
? ? 之前的博客中提到過,我學(xué)習(xí)采用的參考書是《數(shù)據(jù)結(jié)構(gòu)與算法分析——C語言描述》。這門書的組織安排與國內(nèi)廣泛實(shí)用的教材《數(shù)據(jù)結(jié)構(gòu)——C語言版》比較不同。這本書描述了一些樹和二叉樹的概念,舉例講解了什么是樹的三種遍歷之后,就開始重點(diǎn)講解二叉查找樹、平衡二叉樹、AVL樹、伸展樹、B數(shù)了。這一篇博客,重點(diǎn)學(xué)習(xí)二叉查找樹的概念和基本操作。
? ? 大家都知道,樹的定義本身就帶有遞歸性。因此,樹的很多操作都涉及到了遞歸。二叉查找樹的定義如下:
? ? 1.二叉查找樹首先是一棵二叉樹;
? ? 2.二叉查找樹除了是二叉樹外,還具有以下性質(zhì):對于樹中的任何一個節(jié)點(diǎn)X,其左子樹中的所有節(jié)點(diǎn)的關(guān)鍵字均小于X的關(guān)鍵字的值;而其右子樹中的所有關(guān)鍵字的值均大于X的關(guān)鍵字的值。下面兩棵二叉樹中,左邊的二叉樹是二叉查找樹而右邊的不是。
?
? ? 二叉查找樹的數(shù)據(jù)結(jié)構(gòu)定義如下:
typedef?int?ElementType;?typedef?struct?TreeNode?*Position;?typedef?Position?BiSearchTree;?struct?TreeNode?{?????ElementType?Element;?????BiSearchTree?Left,Right;?};? ? ? 二叉查找樹的常用操作如下:
BiSearchTree?MakeEmpty(BiSearchTree?Tree);?Position?Find(ElementType?X,?BiSearchTree?T);?Position?FindMin(BiSearchTree?T);?Position?FindMax(BiSearchTree?T);?BiSearchTree?Insert(ElementType?X,BiSearchTree?T);?BiSearchTree?Delete(ElementType?X,?BiSearchTree?T);? ? ? 二叉排序樹的操作與之前學(xué)習(xí)的一些數(shù)據(jù)結(jié)構(gòu)的操作相比,可能難理解一些。下面我們挑比較難的幾個一一講解。
? ? 1.二叉查找樹中查找指定的元素Find
? ? 二叉排序樹的性質(zhì)是二叉排序樹很多操作的基本依據(jù)。既然要查找指定元素X,先比較X與根節(jié)點(diǎn)元素的關(guān)系,如果剛好相等,直接返回啦;如果X小于根節(jié)點(diǎn)的元素值,那么去根節(jié)點(diǎn)的左子樹中查找,也就是調(diào)用Find方法,只是傳遞的參數(shù)是X和根節(jié)點(diǎn)的左子樹;如果X大于根節(jié)點(diǎn)的元素值,那么去根節(jié)點(diǎn)的右子樹中查找,也就是調(diào)用Find函數(shù),只是傳遞的參數(shù)是X和根節(jié)點(diǎn)的右子樹。
? ? 2.查找最小元素FindMin和最大元素FindMax
? ? 這兩個操作是類似的。采用迭代或者遞歸都可以實(shí)現(xiàn),查找最小元素只需要沿著左子樹訪問下去,查找最大元素則相反。下面我們會分別采用遞歸和迭代實(shí)現(xiàn)這兩個操作。
? ? 3.插入操作Insert
? ? 插入操作其實(shí)類似于查找操作,插入過過程其實(shí)就是先得找到一個合適的位置。插入其實(shí)有下面幾個情況:
? ? (1)如果函數(shù)傳進(jìn)來的是空樹,那么創(chuàng)建一棵樹,將其元素值設(shè)置為X。這種情況顯而易見;
? ? (2)如果不是空樹,那就比較根節(jié)點(diǎn)元素值和X的大小,如果X的值小于根節(jié)點(diǎn)的元素值,而此時的根節(jié)點(diǎn)的左子樹為空,那么根節(jié)點(diǎn)的左孩子就是X元素的歸宿啦;同樣的道理,如果X的值大于根節(jié)點(diǎn)的元素值,而此時根節(jié)點(diǎn)的右子樹為空,那么根節(jié)點(diǎn)的右孩子就是X元素的歸宿啦。把握住這一點(diǎn)其實(shí)基本上就能把握住這個操作了。文字描述可能比較抽象,下面看圖:
? ? 左邊的圖,如果要插入5,沿著樹一直找到節(jié)點(diǎn)4,這時5>4并且4的右孩子為空,那么5就是4的右孩子。右邊的圖,要想插入8,沿著樹找到9,發(fā)現(xiàn)8<9且9的左孩子為空,那么8就是9的左孩子。
? ? 當(dāng)然,在實(shí)現(xiàn)這樣一個過程的時候可以使用遞歸。
? ? 4.刪除操作Delete
? ? 刪除操作是我認(rèn)為最復(fù)雜最不好理解的一個操作。如果沒有仔細(xì)想明白整個過程,上來就看代碼的話可能會很暈。刪除操作分兩步:第一步是查找,找的過程就涉及元素值之間的比較。我們重點(diǎn)說找到之后的操作。假設(shè)我們找到了這個節(jié)點(diǎn),現(xiàn)在要刪除,涉及三種情況:
? ? (1)該節(jié)點(diǎn)是葉子。這還有什么好說的,直接刪了一了百了;
? ? (2)該節(jié)點(diǎn)只有一個孩子節(jié)點(diǎn)。也不復(fù)雜,讓該節(jié)點(diǎn)的父節(jié)點(diǎn)直接指向其子節(jié)點(diǎn)就行了。當(dāng)然,也別忘了回收該節(jié)點(diǎn);
? ? (3)該節(jié)點(diǎn)有兩個孩子:找到該節(jié)點(diǎn)右子樹中最小的節(jié)點(diǎn),將其元素值賦給該節(jié)點(diǎn),然后刪除那個最小節(jié)點(diǎn)。這種情況看圖:
?
? ? 說了半天了,下面看看完整的代碼:
#include?<stdio.h>?#include?<stdlib.h>??typedef?int?ElementType;?typedef?struct?TreeNode?*Position;?typedef?Position?BiSearchTree;?struct?TreeNode?{?????ElementType?Element;?????BiSearchTree?Left,Right;?};???BiSearchTree?MakeEmpty(BiSearchTree?Tree)?{?????if(!Tree)?????{?????????MakeEmpty(Tree->Left);?????????MakeEmpty(Tree->Right);?????????free(Tree);?????}?????return?NULL;?}??Position?Find(ElementType?X,?BiSearchTree?T)?{?????if(T?==?NULL)?????{?????????return?NULL;?????}?????else?????{??????????????????if(X?<?T->Element)?????????{?????????????return?Find(X,T->Left);?????????}?????????else?if(X?>?T->Element)?????????{?????????????return?Find(X,T->Right);?????????}?????????else?????????{?????????????return?T;?????????}?????}?}??Position?FindMin(BiSearchTree?T)?{?????if(T?==?NULL)?????{?????????return?NULL;?????}?????else?????{?????????if(T->Left?==?NULL)??????????{?????????????return?T;?????????}else?????????{?????????????return?FindMin(T->Left);?????????}?????}?}???Position?FindMax(BiSearchTree?T)?{?????if(T->Right?!=?NULL)?????{?????????while(T->Right?!=?NULL)?????????{?????????????T?=?T->Right;?????????}?????}?????return?T;?}??BiSearchTree?Insert(ElementType?X,BiSearchTree?T)?{??????????if(T?==?NULL)?????{?????????T?=?malloc(sizeof(struct?TreeNode));?????????if(T?==?NULL)?????????{?????????????fprintf(stderr,"Out?of?Space!!!");?????????}?????????else?????????{?????????????T->Element?=?X;?????????????T->Left?=?NULL;?????????????T->Right?=?NULL;?????????}?????}??????????else?????{?????????if(X?<?T->Element)??????????{?????????????T->Left?=?Insert(X,T->Left);?????????}?????????else?if(X?>?T->Element)??????????{?????????????T->Right?=?Insert(X,T->Right);?????????}?????????else?????????{??????????????????????}?????}?????return?T;?}???BiSearchTree?Delete(ElementType?X,?BiSearchTree?T)?{?????Position?TmpCell;?????if(T==NULL)?????{?????????fprintf(stderr,"Element?does?not?exist!");?????}?????else?if(X?<?T->Element)?????{?????????T->Left?=?Delete(X,T->Left);?????}?????else?if(X?>?T->Element)?????{?????????T->Right?=?Delete(X,T->Right);?????}?????else?if(T->Left?&&?T->Right)?????{?????????TmpCell?=?FindMin(T->Right);?????????T->Element?=?TmpCell->Element;?????????T->Right?=?Delete(T->Element,T->Right);?????}?????else?????{?????????TmpCell?=?T;?????????if(T->Left?==?NULL)?????????{?????????????T?=?T->Right;?????????}?????????else?if(T->Right?==?NULL)?????????{?????????????T?=?T->Left;?????????}?????????free(TmpCell);?????}?????return?T;?}??int?main(void)?{?????BiSearchTree?T;?????int?index;?????int?arr[10]?=?{10,9,8,7,6,1,2,3,4,5};?????T?=?NULL;?????for(index=0;?index?<?10;?index++)?????{?????????T?=?Insert(arr[index],T);?????}?????T?=?Insert(18,T);?????T?=?Insert(15,T);?????printf("The?minimum?element?is?%d\n",FindMin(T)->Element);?????printf("The?maxmium?element?is?%d\n",FindMax(T)->Element);?????return?0;?}? ?
?
?
?
?
?
?
轉(zhuǎn)載于:https://blog.51cto.com/wawlian/722244
總結(jié)
以上是生活随笔為你收集整理的重学数据结构007——二叉查找树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。