1. 程式人生 > >演算法研究--使用 紅黑樹 解決實際問題(理論與實踐)

演算法研究--使用 紅黑樹 解決實際問題(理論與實踐)

    在查詢中,雖然hash表查詢非常迅速,但是隨著資料的種類增多,
hash表長會變得更長,且衝突也會越來越多,那麼如何能實現無論在
多大資料量的情況下,查詢依然是高效能的呢?

   在1978年,Leo J.Guibas 與 Robert Sedgewick寫了一篇論文中
談到了一種較好的用於查詢的資料結構----紅黑樹

     一般來說,樹是很好的一種資料結構,那用於插入,刪除,查詢等
都是很高效的資料樹構,但問題是在很壞的情況下,操作很費時間,它的
效能得到不保證,比如二叉查詢樹中如果左子樹與右子樹相差太遠,那麼查詢
時就很費時間。這時為了保證其有高效性,就得保證左樹與右樹不能差得太遠,
當向樹中插入時,就按一定規則調整,使其達到規則,從而使其整體與區域性
查詢效率得到提高。這就是紅黑樹的規則.

   這些規則是
在二叉查詢樹的基礎上,
(1)節點都有顏色,要麼黑色,要麼紅色。
(2)根結點是黑色的,葉子結點是黑色的。
(3)每條從樹到葉子的路上沒有二個連續的紅色。即紅色的子樹一定是黑色
(4)各條從葉子到根的路上的黑色結點相同。

關鍵的是(3), (4)它使得樹是區域性是平衡的,並且每條路線不會太長。

   還有一個重要的點就是,為了研究方便,會在紅黑樹補成兩個子樹是完整的,
它們也有顏色,是黑色,但是沒有資料,它稱為nil葉子,null葉子。當搜尋時
發現結點與nil葉子相 等時,則是找到了葉子了。

  另外,關於紅黑樹與平衡二叉樹的區別,它們的區別在概念上也有,
但是在效能上也有,平衡二叉樹也是在最壞的情況下有高效的,但是它
追求整體的平衡,使得調整樹時,會要很長的時間複雜度,而紅黑樹是
區域性平衡,調整時只要0(logn)顏色變數,並且調整不超過三次。


    那麼如何使用紅黑樹來解決問題呢,可以先構造紅黑樹
構造紅黑樹的辦法如下:
(1)定義節點結構,
一般是 值,key, 長度,左指標,右指標,指向父的指標,顏色。

(2)插入
 插入時,先從樹根開始,先校驗樹是不是為空節點或者nil結點,若是
則插入結點為新根,若不是,則與樹比較,小於的話,往左移,大於
往右移,這裡與二叉查詢樹類似,最後再對其顏色進行調整.所謂的調
整隻有4種情況,都設計好了。

(3)查詢
按照二叉查詢樹的樣子進行查詢。


例子:查詢班上姓名為'xiaoming'同學的基本資訊情況
 辦法: 則要以姓名為關鍵字建立一個紅黑樹,建法很多,
可以以其各字母ascii和的辦法作為關鍵字,或以某函式生成一個均可。
   然後樹據關鍵字的值生成紅黑樹,再查詢就可以了

部分MFC程式碼如下:

節點結構。
typedef struct Node
{

 Coulor color;
 int key;
 Node *p,*left,*right;
 int size;
 char *name;               //the description data that the  node contained

}Node,*pNode;

下面的程式碼中,rbInsert(pNode z)為插入建立的函式,
   void rbInsertFixUp(pNode z)為調整區域性色彩的函式。


------------------
//RBTree.h檔案如下

#ifndef RBTREE_H
#define RBTREE_H

#pragma once

#include
#include"MainFrm.h"


enum Coulor{RED,BLACK};
typedef struct Node
{

 Coulor color;
 int key;
 Node *p,*left,*right;
 int size;
 char *name;               //the description data that the  node contained

}Node,*pNode;

 
extern Node Nil;  //ÉÚ±ø
extern const pNode nil;
class rbTree
{
public:
 pNode root;
    pNode  cur;
public:
 rbTree(){root=cur=&Nil;};
 ////////////////////////////
 void setName(pNode x,const char*na)
 {
   x->name=new char[strlen(na)+1];
   strcpy(x->name,na);
 }

    pNode newNode(int k,const char*na="N",pNode pa=nil,pNode le=nil,pNode ri=nil)
 {
  pNode ne=new Node;
  ne->key=k;
  ne->color=RED;
  ne->left=le;
  ne->p=pa;
  ne->right=ri;
  ne->size=1;
  setName(ne,na);
  return ne;
 }
 ////////////////////////////////////////
 //·ÃÎÊp,left,rightµÈ
 pNode &p(pNode x){return x->p;};
 pNode &left(pNode x){return x->left;};
 pNode &right(pNode x){return x->right;};
    int   &size(pNode x){return x->size;};
 Coulor &color(pNode x){return x->color;};
 int   &key(pNode x){return x->key;};

 //
 const pNode  P(pNode x){return x->p;};
 const pNode  Left(pNode x){return x->left;};
 const pNode  Right(pNode x){return x->right;};
    const int    Size(pNode x){return x->size;};
 const Coulor Color(pNode x){return x->color;};
 const int    Key(pNode x){return x->key;};

 ////////////////////////////////////////
 pNode successor(pNode x)
 {
  if(Right(x) != nil)
   return minimum(Right(x));
  pNode y= P(x);
  while ( y!=nil && x==Right(y) )
  {
   x=y;
   y=P(y);
  }
  return y;
 }
 //////////////////////////
 pNode minimum( pNode x)
 {
  while (Left(x)!=nil)
   x=Left(x);
  return x;
 }
 ////////////////////////////
 int Bheight(pNode x)
 {
  pNode y=x;
  int k=0;
  while(y!=nil)
  {
   if(Color(y)==BLACK)
    k++;
   y=Left(y);
  }
  return k;
 }
 ////////////////////////////////////////////////////////////
 //×óÐýת
   void lrotate(pNode x)
   {
    pNode y=Right(x);
    //ά»¤size;
    int sx=x->size;
    int sy=y->size;
    size(y)=sx;
    size(x)=sx-size(Right(y))-1;

    right(x)=Left(y);
    p(Left(y))=x;
    p(y)=P(x);
    if(P(x)==nil)
    {
     root=y;
    }
    else if( x == Left(P(x)) )
    {
     left(P(y))=y;
    }
    else
     right(P(x))=y;
       left(y)=x;
    p(x)=y;
   }
   //ÓÒÐýת
   void rrotate(pNode x)
   {
    pNode y=Left(x);
   
    //ά»¤size;
   
    size(y)=Size(x);
    size(x)=Size(x)-Size(Left(y))-1;

    left(x)=Right(y);
    p(Right(y))=x;
    p(y)=P(x);
    if(P(x)==nil)
    {
     root=y;
    }
    else if(x==Left(P(x)))
    {
     left(P(y))=y;
    }
    else
     right(P(x))=y;
       right(y)=x;
    p(x)=y;
   }
   ///////////////////////////////////////////////
   //²åÈë¼°Æäµ÷Õû
   //²åÈë
   void rbInsert(pNode z)
   {
    pNode y=nil;
    pNode x=root;

    while(x!=nil)
    {
     y=x;
     size(x)=Size(x)+1;
     if(Key(z) < Key(x))
      x=Left(x);
     else
      x=Right(x);
    }
    p(z)=y;
    if(y == nil)
     root=z;
    else if(Key(z)
     left(y)=z;
    else
     right(y)=z;
    rbInsertFixUp(z);


   }
   //µ÷Õû
   void rbInsertFixUp(pNode z)
   {
    while(Color(P(z)) == RED)
    {
     if( P(z) == Left(P(P(z))))
     {
      pNode y=Right(P(P(z)));
         if(Color(y) == RED)
      {
       color(P(z)) = BLACK;
       color(y)= BLACK;
       color(P(P(z))) =RED;
       z=P(P(z));
      }
      else
      {
       if(z == Right(P(z)))
       {
        z=P(z);
           lrotate(z);
       }
       color(P(z))=BLACK;
       color(P(P(z)))=RED;
       rrotate(p(P(z)));
      }
     }
     else
     {
      pNode y=Left(P(P(z)));
         if(Color(y) == RED)
      {
       color(P(z)) = BLACK;
       color(y)= BLACK;
       color(P(P(z))) =RED;
       z=P(P(z));
      }
      else
      {
       if(z == Left(P(z)))
       {
        z=P(z);
           rrotate(z);
       }
       color(P(z))=BLACK;
       color(P(P(z)))=RED;

相關推薦

演算法研究--使用  解決實際問題(理論實踐)

    在查詢中,雖然hash表查詢非常迅速,但是隨著資料的種類增多, hash表長會變得更長,且衝突也會越來越多,那麼如何能實現無論在 多大資料量的情況下,查詢依然是高效能的呢?    在1978年,Leo J.Guibas 與 Robert Sedgewick寫了一

程式設計師面試、演算法研究、程式設計藝術、4大系列集錦總結

作者:July--結構之法演算法之道blog之博主。時間:2010年10月-2011年6月。出處:http://blog.csdn.net/v_JULY_v 。宣告:版權所有,侵犯必究。 前言    開博已過8個月,回首這8個月,發現自己在本blog上著實花費了巨大的時間與精力,寫的東西可能也夠幾本書的內容

演算法-查詢(

查詢 符號表 最主要的目的是將一個鍵合一個值聯絡起來。用例能夠將一個鍵值對插入符號表並希望在之後能夠從符號表的所有鍵值對中按照鍵直接找到對應的值,即以鍵值對為單元的資料結構。 無序連結串列順序查詢 效能:N方 有序陣列二分查詢 程式碼 public int ran

演算法導論 之 - 插入 C語言

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

【資料結構演算法】之 --- 第十四篇

樹是一種非線性資料結構,這種資料結構要比線性資料結構複雜的多,因此分為三篇部落格進行講解: 第一篇:樹的基本概念及常用操作的Java實現(二叉樹為例) 第二篇:二叉查詢樹 第三篇:紅黑樹 第三篇:紅黑樹 開篇說明:對於紅黑樹的學習,近階段只需要掌握這種資料結構的思想、特點、適

演算法導論中插入演算法的C+實現及優化改進

之前在上到算導的紅黑樹插入時,突然冒出個想法,下課的時候找徐教授交流,由於當時也沒想透徹加上表述不清,就沒深入下去。恰巧實驗課要做紅黑樹插入的實現,於是整理了一番,記錄於此以備以後檢視。 由於C++水平太菜,程式碼基本用C實現,用到了一些C++的新特性。 首先是結點的資料

演算法導論 之

作者:鄒祁峰 郵箱:[email protected] 日期:2013.12.27 16:45 轉載請註明來自"祁峰"的CSDN部落格 1 引言   博文《演算法導論 之 平衡二叉樹 - 列印》中使用遞迴演算法實現了平衡二叉樹的列印功能,仿照此博文中的程式碼可

演算法--我的學習過程

其他更多java基礎文章: java基礎學習(目錄) 學習資料: 紅黑樹詳細分析,看了都說好 紅黑樹刪除操作 碼圖並茂紅黑樹 紅黑樹從頭至尾插入和刪除結點的全程演示圖 閱讀前提 在研究集合類原始碼的時候,發現Map,Set裡面不少用到紅黑樹,為了能夠更順利的學習原始碼。我決定把紅黑樹知識惡

演算法插入資料的情況實現(三)

大家如果有玩魔方,我相信是可以理解我說的東西的,轉魔方就是先把第一面轉出來,然後把第一面作為底面,然後根據遇見的情況來轉魔方(是有公式的) 該系列到現在暫只有3篇文章:   【演算法】紅黑樹(二叉樹)概念與查詢(一):https://blog.csdn.net/lsr40/ar

演算法導論學習--詳解之刪除(含完整程式碼)

前面我們討論了紅黑樹的插入的實現,基本思想是分類討論;然後分情況討論以後我們發現插入操作調整函式只需要處理三種情況,並不是太複雜。但是刪除操作會更復雜一點,因為二叉搜尋樹的刪除操作本身就分成了多種情況,這樣在執行刪除操作後要處理的情況會更多;下面對於刪除操作我們

演算法導論 之 - 刪除 C語言

                作者:鄒祁峰 郵箱:[email protected] 部落格

演算法導論》詳解(二):Java實現Demo

使用Java簡單地實現紅黑樹,程式碼如下: /** * 紅黑樹實現demo */ public class RedBlackTree<Key extends Comparable<Key>> { private stati

資料結構演算法簡記:

上次記錄了AVL樹的相關內容,其規定節點左右子樹高度之差不超過1,在新增或移除多個節點後能夠對自身重新建立平衡,使其仍可維持一棵良好的二叉查詢樹結構,不過AVL樹為了維護良好的結構,在新增或刪除頻繁時,效能也會相應的下降。一種替代的方案是使用紅黑樹。 紅黑樹(

java資料結構和演算法06(

  這一篇我們來看看紅黑樹,首先說一下我啃紅黑樹的一點想法,剛開始的時候比較蒙,what?這到底是什麼鬼啊?還有這種操作?有好久的時間我都緩不過來,直到我玩了兩把王者之後回頭一看,好像有點兒意思,所以有的時候碰到一個問題困擾了很久可以先讓自己的頭腦放鬆一下,哈哈!   不瞎扯咳,開始今天的正題;   前提:看

stl map底層之插入步驟詳解程式碼實現

本篇文章並沒有詳細的講解紅黑樹各方面的知識,只是以圖形的方式對紅黑樹插入節點需要進行調整的過程進行的解釋。 最近在看stl原始碼剖析,看到map底層紅黑樹的實現。為了加深對於紅黑樹的理解就自己動手寫了紅黑樹插入的實現。關於紅黑樹插入節點後破壞紅黑樹性質的幾種情況,可以在網

8.的定義,的效能分析和平衡二叉的比較

平衡二叉樹 平衡二叉樹或者是一顆空的二叉排序樹,或是具有下列性質的二叉排序樹: 根節點的左子樹和右子樹的深度最多相差1根節點的左子樹和右子樹都是平衡二叉樹 平衡因子 平衡因子是該節點的左子樹的深度與右子樹的深度之差。 最小不平衡子樹 在平衡二叉樹的構造過程中,以距離插入節

程式設計師面試 演算法研究 程式設計藝術 機器學習5大系列集錦

                                程式設計師面試、演算法研究、程式設計藝術、紅黑樹、機器學習5大經典原創系列集錦與總結作者:July--結構之法演算法之道blog之博主。時間:2010年10月-2018年5月,一直在不斷更新中..出處:http://blog.csdn.net/v

程式設計師面試、演算法研究、程式設計藝術、、機器學習5大系列集錦

                程式設計師面試、演算法研究、程式設計藝術、紅黑樹、機器學習5大經典原創系列集錦與總結 作者:July--結構之法演算法之道blog之博主。 時間:2010年10月-2018年5月,一直在不斷更新中.. 出處:http://blog.

程式設計師面試、演算法研究、程式設計藝術、、資料探勘5大經典原創系列集錦總結

作者:July--結構之法演算法之道blog之博主。 時間:2010年10月-2012年9月 (一直在收錄本blog最新updated文章)。 出處:http://blog.csdn.net/v_JULY_v 。 宣告:版權所有,侵犯必究。 前言    開博已過20個

程式設計師面試、演算法研究、程式設計藝術、、機器學習5大系列集錦(轉)

原文連結:https://blog.csdn.net/v_july_v/article/details/6543438   重大訊息:經過反覆修改、優化,程式設計藝術系列最終成書出版,並改名為《程式設計之法:面試和演算法心得》,目前京東、噹噹、亞馬遜等各大網店均已有現貨銷售。