二叉排序樹研究

    數據結構中的二叉排序樹研究,做個記錄。

(1)二叉排序樹概念(二叉查找樹)

它是一顆空樹,或者具有以下性質的二叉樹。

a、若它的左子樹不爲空,則左子樹上所有結點值均小於它的根結點的值

b、若它的右子樹不爲空,則左子樹上所有結點值均大於它的根結點的值

c、左右子樹有分別是二叉排序樹

(2)二叉排序樹查找操作

二叉排序樹結點結構體:

typedef struct BiTNode          //結點結構體
{
   int data;
   struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
查找代碼如下:

/*********************************************
**功能:遞歸查找二叉排序樹中是否存在key
**T:二叉排序樹
**key:鍵值
**f:指向T的雙親
**p:如果查找成功  指向該數據元素結點       否則指向查找路徑上訪問的最後一個結點,並返回一個false
*********************************************/
int SearchBST(BiTree T,int key,BiTree f,BiTree *p)
{
   if (!T)        //查找不成功
   {
      *p = f;
      return 0;
   }
   else if (key == T->data)          //找到了鍵值
   {
      *p = T;
      return 1;
   }
   else if (key < T->data)           //左子樹繼續查找
   {
     return SearchBST(T->lchild,key,T,p);      
   }
   else                             //右子樹中繼續查找
   {
      return SearchBST(T->rchild,key,T,p);      
   }
}
(3)二叉排序樹插入操作
/*********************************************
**功能:二叉排序樹插入操作,如果二叉排序樹中不存在關鍵字等於key的數據元素時,插入key並返回true,否則返回false
**T:二叉排序樹
**key:關鍵字
*********************************************/
int InsertBST(BiTree *T,int key)
{
   BiTree  p,s;           //兩個臨時變量,p指向查找路徑上的最後一個結點;s用於新插入的結點
   if (!SearchBST(*T,key,NULL,&p))       //查找不成功時進行插入
   {
      s = (BiTree)malloc(sizeof(BiTNode));
      s->data = key;
      s->lchild = s->rchild = NULL;
      if (!p)                       //表示一顆空樹
      {
         *T = s;
      }
      else if (key < p->data)      //插入到左子樹
      {
         p->lchild = s;
      }
      else                         //插入到右子樹
      {
         p->rchild = s;
      }
      return 1;
   }
   else
   {
      return 0;
   }
}
(4)二叉排序樹刪除操作

刪除操作稍微麻煩寫,分三種情況討論

a、待刪除結點是葉子結點(直接刪除)

b、待刪除結點僅有左或者右子樹(子承父業)

c、待刪除結點左右子樹同時存在(找到待刪除結點的直接前驅,用直接前驅替換當前點,然後重接左或右子樹)

代碼如下:

/*********************************************
**功能:二叉排序樹刪除操作,如果二叉排序樹中存在關鍵字等於key的數據元素時,刪除該數據元素結點,並返回true,否則返回false
**T:二叉排序樹
**key:關鍵字
*********************************************/
int DeleteBST(BiTree* T,int key)
{
   if (! *T)    //不存在關鍵字等於key的數據元素
   {
      return 0;
   }
   else
   {
      if (key == (*T)->data)             //找到關鍵字等於key的結點
      {
         return Delete(T);
      }
      else if (key < (*T)->data)
      {
         return DeleteBST(&(*T)->lchild,key);      
      }
      else
      {
         return DeleteBST(&(*T)->rchild,key);
      }
   }
}
真正執行刪除操作的是Delete()函數,代碼如下:

/*********************************************
**功能:二叉排序樹中刪除結點p,並重接左右子樹
**p:待刪除的結點
*********************************************/
int Delete(BiTree *p)
{
   //分三種情況討論:待刪除的結點  1、葉結點  2、僅有左或右子樹  3、左右子樹同時存在
   BiTree q,s;
   if (!(*p)->rchild)      //如果右子樹爲空,只需要重接左子樹即可
   {
      q = *p;               //暫存
      *p = (*p)->lchild;    //覆蓋
      free(q);              //刪除
   }
   else if (!(*p)->lchild)    //如果左子樹爲空,只需要重接右子樹即可
   {
      q = *p;               //暫存
      *p = (*p)->rchild;    //覆蓋
      free(q);              //刪除
   }
   else
   {
      q = *p;
      s = (*p)->lchild;
      while (s->rchild)         //轉左,然後向右到盡頭(找到待刪除結點的前驅)
      {
         q = s;
         s = s->rchild;
      }
      (*p)->data = s->data;         //s指向被刪除結點的直接前驅
      if (q != *p)                  
      {
         q->rchild = s->lchild;     //重接q的右子樹
      }
      else
      {
         q->lchild = s->lchild;     //重接q的左子樹
      }
      free(s);
   }
   return 1;
}

測試如下:

/*********************************************
**功能:二叉排序樹刪除操作,如果二叉排序樹中存在關鍵字等於key的數據元素時,刪除該數據元素結點,並返回true,否則返回false
**T:二叉排序樹
**key:關鍵字
*********************************************/
int DeleteBST(BiTree* T,int key)
{
   if (! *T)    //不存在關鍵字等於key的數據元素
   {
      return 0;
   }
   else
   {
      if (key == (*T)->data)             //找到關鍵字等於key的結點
      {
         return Delete(T);
      }
      else if (key < (*T)->data)
      {
         return DeleteBST(&(*T)->lchild,key);      
      }
      else
      {
         return DeleteBST(&(*T)->rchild,key);
      }
   }
}

/*********************************************
**功能:遞歸打印二叉樹,中序遍歷
**T:二叉排序樹
*********************************************/
void PrintBTree(BiTree T)
{
   if (!T)                    //遞歸出口
      return;
   PrintBTree(T->lchild);
   printf("%d\t",T->data);
   PrintBTree(T->rchild);
}
int _tmain(int argc, _TCHAR* argv[])
{
   int a[] = {62,88,58,47,35,73,51,99,37,93};
   BiTree T = NULL;
   for (int i=0;i<10;++i)
   {
      InsertBST(&T,a[i]);
   }
   PrintBTree(T);
   DeleteBST(&T,58);
   PrintBTree(T);
   return 0;
}
結果有圖爲證:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章