二叉尋找樹描述
二叉尋找樹的性質:對於樹中的每個結點X,它的左子樹中所有關鍵字值小於X的關索引值,而它的右子樹中所有關鍵字大於X的關索引值。由於樹的遞迴定義,通常是遞迴的編寫尋找樹的常用操作常式。對這些常用常式中,主要需要考慮的是插入和刪除節點。下面將簡要說明。(二叉尋找樹的平均深度是O(logN),所以一般不需要擔心棧空間用盡。)
Insert:為了將X插入到樹T中,可以像用Find那樣沿著樹尋找。如果找到X,則什麼也不用做。否則,將X插入到遍曆的路徑上的最後一點上。如所示,為了插入5,因而遍曆該樹,就好像在運行Find。在具有關鍵字4的節點處需要向右行進,但4的右子樹不存在,因此5不在這棵樹上,從而這個位置就是所要插入的位置。
Delete:一旦發現要刪除的節點,考慮以下三種情況:如果該節點是一片樹葉,那麼它可以被立即刪除;如果節點只有一個兒子,則該節點可以在其父節點調整指標繞過該節點後被刪除,如:刪除只有一個左孩子節點的元素:4。
複雜的情況是處理具有兩個兒子的節點。一般的刪除策略是用其右子樹關鍵字最小的元素或左子樹關鍵字最大的元素代替該節點的資料並遞迴的刪除那個節點。因為右子樹中最小節點不可能有左孩子(左子樹的最大值節點則不可能有右孩子),所以第二次Delete變要容易一些。是一顆初始的二叉尋找樹即刪除關鍵字為2的節點後的狀態。
二叉尋找樹的具體代碼實現
標頭檔:searchTree.h
typedef int ElementType;#ifndef _SEARCH_TREE_#define _SEARCH_TREE_struct TreeNode;typedef TreeNode *Position;typedef TreeNode *SearchTree;SearchTree MakeEmpty( SearchTree T ); //釋放樹中的所有元素Position Find( ElementType X, SearchTree T ); Position FindMin( SearchTree T ); //尋找最小值Position FindMax( SearchTree T );SearchTree Insert( ElementType X, SearchTree T );SearchTree Delete( ElementType X, SearchTree T );ElementType Retrieve( Position P ); //提取該位置上關鍵字void PrintTree( SearchTree T ); //先序輸出#endif
實現檔案:SearchTree.c
#include "searchTree.h"#include <stdio.h>#include <stdlib.h>struct TreeNode{ElementType Element;Position Left;Position Right;};SearchTree MakeEmpty( SearchTree T ){if (T != NULL){MakeEmpty(T->Left);MakeEmpty(T->Right);free(T);}return NULL;}Position Find( ElementType X, SearchTree T ){if (T == NULL)return NULL;if (T->Element < X)return Find(X, T->Right);else if(T->Element > X)return Find(X, T->Left);else return T;//非遞迴實現/*while (T != NULL){if (T->Element < X)T = T->Left;else if (T->Element > X)T = T->Right;else return T;}*/}Position FindMin( SearchTree T ){if (T == NULL)return NULL;else if (T->Left == NULL)return T;else return FindMin(T->Left);//非遞迴實現/*Position P = T;while (P->Left != NULL){P = P->Left;}return P;*/}Position FindMax( SearchTree T ){if (T == NULL)return NULL;else if (T->Right == NULL)return T;else return FindMax(T->Right);//非遞迴實現/*Position P = T;while (P->Right != NULL){P = P->Right;}return P;*/}SearchTree Insert( ElementType X, SearchTree T ){if (T == NULL){//最後該插入X的位置T = (Position)malloc(sizeof(struct TreeNode));if (T == NULL){printf("Out of space!\n");return NULL;}T->Left = T->Right = NULL;T->Element = X;}else if (T->Element < X)T->Right = Insert(X, T->Right);else if (T->Element > X)T->Left = Insert(X, T->Left);return T;}SearchTree Delete( ElementType X, SearchTree T ){Position TmpCell;if (T == NULL) printf("Cannot find element %d\n", X);else{if (X < T->Element) //在左子樹中尋找T->Left = Delete(X, T->Left);else if (X > T->Element)T->Right = Delete(X, T->Left);else{//找到值為X的節點,即此時的T,判斷該節點的左右孩子是否都存在if (T->Left && T->Right){TmpCell = FindMin(T->Right); //找到右子樹中的最小者T->Element = TmpCell->Element;T->Right = Delete(T->Element, T->Right); //改為刪除T右子樹中最小者}else{ TmpCell = T; if ( T->Left == NULL) T = T->Right; else if ( T->Right == NULL ) T = T->Left; free(TmpCell);}}}return T;} void PrintTree( SearchTree T ){if (T != NULL){printf("%5d\n", T->Element);PrintTree(T->Left);PrintTree(T->Right);}}ElementType Retrieve( Position P ){return P->Element;}