數據結構八(查找)

左旋](http://upload-images.jianshu.io/upload_images/851071-a9ebfb00c1210d4d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

查找:就是根據給定的某個值,在查找表中確定一個其關鍵字等于給定值的數據元素(或記錄)

查找表按照操作方式分為兩大種:靜態查找表動態查找表.
靜態查找表:只做查找操作的查找表.它的主要操作有:
1.查詢某個'特定的'數據元素是否在查找表中
2.檢索某個'特定的'數據元素和各種屬性
動態查找表:在查找過程中同時插入查找表中不存在的數據元素,或者從查找表中刪除已經存在的某個數據元素.注意操作:
1.查找時插入數據元素
2.查找時刪除數據元素

2.順序表查找

順序查找又叫線性查找,是最基本的查找技術,它的查找過程是:從表中第一個(或最后一個)記錄開始,逐個進行記錄的關鍵字和給定值比較,若某個記錄的關鍵字和給定值相等,則查找成功,找到所查的記錄;如果直到最后一個(或第一個)記錄,其關鍵字和給定值比較都不等時,則表中沒有所查的記錄,查找不成功

查找表算法:
//順序查找,a為數組,n為要查找的數組個數,key為要查找的關鍵字
int Sequential_Search(int *a,int n,int key){
        int i;
        for (i = i; i <= n; i++){
              if (a[i] == key)
                 return i;
       }
       return 0;
}

順序表查找優化
設置哨兵,可以解決每次讓i與n作比較

int Sequetial_Search2 (int *a,int n,int key){
        int i;
        a[0] = key;//設置a[0]為關鍵字,我們稱為"哨兵"
        i = n;//循環從數組尾部開始
        while(a[i] != key){{
              i--;
          }
        return i ;//返回0則說明查找失敗
    }
    順序查找技術有很大的缺點,n很大事,查找效率極為低下,優點是,算法簡單,對靜態查找表的記錄沒有任何要求,在一些小型數據的查找,也是可以適用的

3.有序表查找

1.折半查找

  折半查找技術,又稱為二分查找,他的前提是線性表中的記錄必須是關鍵碼有序(通常從小到達有序),線性表必須采用順序存儲.折半查找的基本思想是:在有序表中,取中間記錄作比較對象,若給定值與中間記錄的關鍵字相等,則查找成功;若給定值小于中間記錄的關鍵字,則在中間記錄的關鍵字,則在中間記錄的左半區繼續查找;若給定值大于中間記錄的關鍵字,則在中間記錄的右半區繼續查找.不斷重復上述過程,直到查找成功,或所有查找區域無記錄,查找失敗為止.

有序表數組{0,1,16,24,35,47,59,62,73,88,99},除0下標外共10個數字對它進行查找是否存在62這個樹

//折半查找
int Binary_Search (int *a, int n ,int key){
      int low,high,mid;
      low = 0;//定義最低下標為記錄首位
      high = n;//定義最高下標為記錄末位
      while(low <=hight){
            mid = (low + high) / 2;//折半
            if (key < a[mid])//若查找值比中指小
                  high = mid - 1;//最高下標調整到中位下標小一位
            else if (key > a[mid])//若查找值比中值大
                  low = mid + 1;//最低下標調整到中位下標大衣位
             else 
                 return mid;//若相等則說明mid即為查找到的位置
          }
         return 0;
 }

1.程序開始運行,參數a={0,1,16,24,35,47,59,62,73,88,99},n=10,key= 62,第3~5行,此時low-1,high = 10


2.mid = (0+ 10) / 2 = 5,a[5] =47 < key,所以執行第12行 low = 5+1 = 6

3.mid = (6+ 10)/2 = 8,a[8] = 73> key,所以執行第10行,high= 8 - 1= 7


4.mid =(6 + 7)/ 2 = 6 ,a[6] = 59< key,執行第12行.low = 6+1=7

將其繪制成二叉樹

2.插值查找

你一定會想,為什么非得折半,為什么不可以四分之一或者更多那.這一點算法數學家已經考慮了,而且還改進了折半查找的算法
折半查找代碼的第八句,我們使用等式變換后得到:
mid = (low + high) / 2 = low + 1 * (hight - low)/ 2,算法數學家將1/2進行改進,得到

改進后的

........啥,,你問我怎么改的,來,過來~,靠近點,看我不打死你,這樣就沒人知道我也不會了
那現在不問了吧,咱們接著往下扯,呸~咱們接著往下學

//插值查找
int Interpolation_Search (int *a, int n ,int key){ 
int low,high,mid; low = 0;//定義最低下標為記錄首位
 high = n;//定義最高下標為記錄末位
 while(low <=hight){ 
      **mid = low +( key - a[low]) * (high - low) /a[high] - a[low];**//插值查找
      if (key < a[mid])//若查找值比中指小 
          high = mid - 1;//最高下標調整到中位下標小一位 
      else if (key > a[mid])//若查找值比中值大
           low = mid + 1;//最低下標調整到中位下標大衣位 
      else 
            return mid;//若相等則說明mid即為查找到的位置
       } 
      return 0;
     }

3.斐波那契查找

斐波那契查找,利用黃金分割的原來來實現的,黃金分割哦~


表情

提起斐波那契數列,一定會想到那個經典的兔子生兔子的命題,就不詳細介紹了

 //斐波那契查找
int Fibonacci_Search(int * a, int n , int key){
    
    int low, high, mid, i, k;
    low = 0;//定義最低下標為記錄首位
    high = n;//定義最高下標為記錄首位
    k = 0;
    while (n > F[k] - 1) //計算n位于斐波那契數列的位置
        k++;
    for (i= n;i : F[k] - 1; i++)//將不滿的數值補全
        a[i] = a[n];
    while (low <= high){
        mid = low + F[k - 1] - 1;計算當前分隔的下標
        if (key < a[mid]){ //若查找記錄小于當前分隔記錄
            high = mid - 1; //最高下標調整到分隔下標mid - 1處
            k =k - 1;//斐波那契數列下標-1
        }
        else if(key > a[mid]){ //若查找記錄大于當前分隔記錄
            low = mid + 1;//最低下標調整到分隔下標+ 1處
            k = k + 2;
        }else{
            if (mid < = n) {
                return mid; //若相等則說明mid即為查找到的位置
            }else{
                return n;//若mid > n,說明是補全數組,返回n
            }
        }
    }
    return 0;
}

4.二叉排序樹

對集合{21,28,14,32,25,18,11,30,19,15}做查找,我們打算創建此集合時就考慮二叉樹結構,而且是排序好的二叉樹,集合的第一個元素21,做根結點,比他小的為左子樹,大的為右子數

排序

我們對他進行中序遍歷,即可得到一個有序的序列{11,14,15,19,18,21,25,28,30,32},所有我們通常稱他為二叉排序樹
二叉排序樹,又稱為二叉查找樹.它或者是一棵空樹,或者是具有下列性質的二叉樹

  • 1.若它的左子樹不空,則左子樹上所有結點的值均小于它的根結構的值
  • 2.若它的右子樹不空,則右子樹上所有結點的值均大于它的根結點的值
  • 3.它的左,右子樹也分別為二叉排序樹

左子樹結點一定比其雙親結點小,右子樹結點一定比其雙親結點大

5.二叉排序樹查找操作
 //二叉樹定義
typedef struct BitNode  //結點結構
{
       int data; //結點數據
      struct BitNode *lchild,*rchild;//左右孩子指針
}BitNode , *BiTree;

//二叉排序樹的查找實現
//遞歸查找二叉排序樹T中是否存在key
//指針f指向T的雙親,其初始調用值為NULL
//若查找成功,則指針p指向該數據元素結點,并返回TRUE
//否則指針p指向查找路徑上訪問的最后一個結點并返回FALSE
Status SearchBST(BiTree T, int key , BiTree f,BiTree * p){
      if (!T) { //查找不成功
          *p = f;
          return FALSE;
      }
      else if (key == T -> data) {//查找成功
             *p = T;
             return TRUE;
      }else if (key < T -> data)
            return SearchBST (T -> lchild, key , T, p); //在左子樹繼續查找
       else
            return SearchBST(T -> rchild, key, T, p);//在右子樹繼續查找
        }
查找樹

由圖可以看成,使用二叉樹查找只需要三步即可,而使用有序的數組需要10步

6.二叉排序樹的刪除操作

我們對刪除結點三種情況的分析

  • 1.葉子結點

  • 2.僅有左或右子樹的結點

  • 3.左右子樹都有的結點

    //若二叉排序樹中存在關鍵字等于key的數據元素,則刪除該數據元素結點
    //并返回TRUE ,否則返回FALSE
    Status DeleteBST (BiTree *T, int key){
           if (!T) //不存在關鍵字等于key的數據元素
                    return FALSE;
            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);
                      }
                }
    
     //重點來了 ......
     Status Delete(BiTree *p ) {
           BiTree q,s;
          if ((*p) -> rchild == NULL) //右子樹空則只需要重接它的左子樹
                  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 TRUE;
         }  
    

如果前面的代碼,看不下去的話,這里是重點!!!!!

思路:被刪除結點A的左子樹的最右結點或A的右子樹的最左結點作為替代A的結點,并修改相應的最左或最右結點的父節點的指針

7.平衡二叉樹

平衡二叉樹是一種**二叉排序樹**,其中每一個節點的左子樹和右子樹的高度差至多等于1,那么平衡二叉樹的平衡因子只可能是-1,0和1

我們將二叉樹上結點的左子樹深度減去右子數深度的值稱為平衡因子

平衡二叉樹.png

距離插入節點最近的,且平衡因子的絕對值大于1的結點為根的子樹,我們稱為最小不平衡子樹

最小不平衡二叉樹
 當新插入結點37時,距離它最近的平衡因子絕對值超過1的結點是58(即它的左子樹高度2減去右子數高度0),所有從58開始以下的子樹為最小不平衡子樹

8.平衡二叉樹實現原理

數組a[10] = {3,2,1,4,5,6,7,10,9,8}需要構建平衡二叉樹

構建平衡二叉樹 一
構建平衡二叉樹 二.png
左旋.gif
右旋.gif
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • 第一章 緒論 什么是數據結構? 數據結構的定義:數據結構是相互之間存在一種或多種特定關系的數據元素的集合。 第二章...
    SeanCheney閱讀 5,807評論 0 19
  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結點至多有m個孩子。 除根結點和葉子結點外,其它每個結點至少有m...
    文檔隨手記閱讀 13,289評論 0 25
  • 前面介紹了基本的排序算法,排序通常是查找的前奏操作。這篇介紹基本的查找算法。 目錄: 1、符號表 2、順序查找 3...
    Alent閱讀 892評論 0 12
  • 數據結構與算法--二叉查找樹 上節中學習了基于鏈表的順序查找和有序數組的二分查找,其中前者在插入刪除時更有優勢,而...
    sunhaiyu閱讀 1,917評論 0 9
  • 曾經我遇見你,遇見星星 在暗夜里猶獨自歡喜, 我看見彩虹和大海, 我看見桃花正在盛開。 曾經我失去你, 再也沒有你...
    釋迦干屎橛閱讀 156評論 0 2