數(shù)據(jù)結(jié)構(gòu)之查找

數(shù)據(jù)結(jié)構(gòu)之查找

查找概論

查找表

定義

查找表(Search Table)是同一類型的數(shù)據(jù)元素(或記錄)的集合哗魂。

查找表分類

靜態(tài)查找表

靜態(tài)查找表(Static Search Table):只做查找操作的查找表。

它的主要操作有:

  1. 查找某個“特定的”數(shù)據(jù)元素是否存在于查找表中疏之。
  2. 檢索某個“特定的”數(shù)據(jù)元素和各種屬性。
動態(tài)查找表

動態(tài)查找表(Dynamic Search Table):在查找過程中同時插入不存在的數(shù)據(jù)元素速挑,
或在查找過程中刪除已經(jīng)存在的數(shù)據(jù)元素谤牡。

它的主要操作有:

  1. 查找時插入數(shù)據(jù)元素。
  2. 查找時刪除數(shù)據(jù)元素姥宝。

關(guān)鍵字

關(guān)鍵字(Key)是數(shù)據(jù)元素中某個數(shù)據(jù)項的值翅萤,又稱為鍵值。(難理解)

若此關(guān)鍵字可以唯一地標識一個記錄腊满,則稱此關(guān)鍵字為主關(guān)鍵字(Primary key)套么。

可以識別多個數(shù)據(jù)元素(或記錄)的關(guān)鍵字,是次關(guān)鍵字(Secondary Key)碳蛋。
意思是根據(jù)次關(guān)鍵字可以查詢到多條數(shù)據(jù)元素嗎胚泌?

查找定義

查找(Searching)是根據(jù)給定的某個值,在查找表中確定一個其關(guān)鍵字等于給定
值的數(shù)據(jù)元素(或記錄)疮蹦。

若查找到了數(shù)據(jù)元素诸迟,則查找成功;否則愕乎,查找失敗阵苇。

查找結(jié)構(gòu)

面向查找操作的數(shù)據(jù)結(jié)構(gòu)叫做查找結(jié)構(gòu)。

順序表查找

概念

順序表查找(Sequential Search)又叫線性查找感论,是最基本的查找技術(shù)绅项。它的查找過程是:

  1. 從表中第一個(或最后一個)記錄開始,逐個比較記錄的關(guān)鍵字和給定值比肄。

  2. 若某個記錄的關(guān)鍵字和給定值相等快耿,則查找成功。

  3. 若一直查找到最后一個(或第一個)記錄芳绩,其關(guān)鍵字都不等于給定值掀亥,則查找失敗。

代碼

int Sequential_search(int *a, int n, int key)
{
    int i;
    for(i = 1; i < n; i++){
        if(a[i] == key){
            return i;
        }
    }
    return 0;
}

順序表查找代碼優(yōu)化

int Sequential_search(int *a, int n, int key)
{
    int i;
    a[0] = key;
    i = 1;
    while(a[i] != key){
        i--;
    }
    return i;   // 當i等于0時查找失敗
}

int Sequential_search(int *a, int n, int key)
{
    int i;
    a[n-1] = key;
    while(a[i] != key){
        i++;
    }
    return i;   // 當i等于n-1時查找失敗
}

時間復雜度

$O(n)$

有序表查找

折半查找

摘抄

一看就懂的知識點妥色,一般不再打字記錄筆記搪花,直接摘抄書本。

數(shù)據(jù)結(jié)構(gòu)_查找_折半查找

代碼

int Binary_search(int *a, int n, int key)
{
    int low, high, mid;
    low = 1;
    high = n;
    while(low <= high){
        /*1*/ mid = (low + high) / 2;
        if(key > a[mid]){
            low = mid + 1;
        }else if(key < a[mid]){
            high = mid - 1;
        }else{
            return mid;
        }
    }
    /*2*/ return 0;
}

第1行嘹害,取值相當于PHP中的 floor 函數(shù)撮竿。

第2行,查找結(jié)果不是 mid 就是查找失敗笔呀。這說明幢踏,若查找表中存在要
查找的關(guān)鍵字,那么該關(guān)鍵字的位置一定是某個中間位置许师。不能理解這點房蝉。

差值查找

差值計算公式

$key-a[low]\over a[high]-a[low]$

這個公式是如何得到的僚匆?

代碼

int Binary_search(int *a, int n, int key)
{
    int low, high, mid;
    low = 1;
    high = n;
    while(low <= high){
        mid = (key - a[low]) / (a[high] - a[low]);
        if(key > a[mid]){
            low = mid + 1;
        }else if(key < a[mid]){
            high = mid - 1;
        }else{
            return mid;
        }
    }
    /*2*/ return 0;
}

時間復雜度

$O(logn)$

斐波那契查找

代碼

int Fibonacci_Search(int *a, int n, int key)
{
    int low, high, mid, i, k;
    low = 1;
    high = n;
    k = 0;
    /*1*/ while(n>F[k]-1){  // 計算n位于斐波那契數(shù)列的位置
        k++;
    }
    for(i = n; i < F[k]-1; i++){    // 將不滿的數(shù)值補全
        a[i] = a[n];
    }
    while(low <= high){
        mid = low + F[k-1] - 1;     // 計算當前分隔的下標
        if(key < a[mid]){
            high = mid - 1;
            /*2*/ k = k -1; // 斐波那契數(shù)列下標減一位
        }else if(key > a[mid]){
            low = mid + 1;
            /*3*/ k = k - 2;    // 斐波那契數(shù)列下標減二位
        }else{
            if(mid <= n){
                return mid;     // 若相等則說明mid即為查找到的位置
            }else{
                return n;       // 若mid>n說明是補全數(shù)值,返回n
            }
        }
    }
    return 0;
}

理解不了第1行搭幻、第2行白热、第3行。

摘抄

數(shù)據(jù)結(jié)構(gòu)_查找_斐波那契查找_核心

不理解上圖中的范圍個數(shù)是怎么得到的粗卜。

數(shù)據(jù)結(jié)構(gòu)_查找_斐波那契查找_范圍個數(shù)示意圖

這個圖好像有助于理解某些東西。

線性索引查找

摘抄

概念

數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_概念

稠密索引

概念
數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_稠密索引_概念

對于稠密索引的的索引表纳击,索引項一定是按照關(guān)鍵碼有序的排列琐驴。

分塊索引

概念
數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_分塊索引_概念

數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_分塊索引_例子
時間復雜度(不懂)
數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_分塊索引_時間復雜度

倒排索引

概念
數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_倒排索引_概念
存儲技巧
數(shù)據(jù)結(jié)構(gòu)_查找_線性索引查找_倒排索引_存儲技巧

二叉排序樹

二叉排序樹查找操作代碼

typedef struct BiTNode
{
    int data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

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->rchild, key, T, p);
    }else{
        return SearchBST(T->lchild, key, T, p);
    }
}

二叉排序樹插入操作代碼

二叉排序樹插入操作代碼

Status InsertBST(BiTree *T, int key)
{
    BiTree 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->rchild = s;
        }else{
            p->lchild = s;
        }
        return TRUE;
    }else{
        return FALSE;
    }
}

如果查找到的是葉子結(jié)點昙读,插入新的結(jié)點很容易。

如果查找到的不是葉子結(jié)點,假如此結(jié)點剛好有左右孩子結(jié)點枫绅,如何插入新的結(jié)點?

查找停止的情況有兩種:找到了和關(guān)鍵字匹配的記錄港庄;查找失敗甸祭。第二種情況,必然
是遍歷到了葉子結(jié)點善已。好不能透徹地理解這點灼捂,只能大概不確定地得出這樣的結(jié)論。

創(chuàng)建二叉排序樹代碼

int CreateBST(void)
{
    int i;
    int a[10] = {62, 88, 58, 47, 35, 73, 51, 99, 37, 93};
    BiTree T = NULL;
    for(i = 0; i < 10; i++){
        InsertBST(T, a[i]);
    }
    
    return 0;
}

二叉排序樹刪除操作代碼

代碼

Status Delete(BiTree *p)
{
    BiTree q, s;
    if((*p)->rchild == NULL){
        q = *p;
        *p = (*p)->lchild;
        free(q);
    }else if((*p)->lchild == 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;
        if(q != *p){
            q->rchild = s->lchild;
        }else{
            q->lchild = s->lchild;
        }
        free(s);
    }
}

二叉排序樹刪除結(jié)點代碼

Status DeleteBST(BiTree *T, int key)
{
    if(!*T){
        return FALSE;
    }else{
        if(key == (*T)->data){
            return Delete(T);
        }else if(key < (*T)->data){
            return DeleteBST(&(*T)->lchild, key);
        }else{
            return DeleteBST(&(*T)->rchild, key);
        }
    }
}

刪除操作有四種情況:

  1. 要刪除的結(jié)點是葉子結(jié)點换团。
  2. 要刪除的結(jié)點有左孩子悉稠。
  3. 要刪除的結(jié)點有右孩子。
  4. 要刪除的結(jié)點有左右孩子艘包。理解不了這種情況的代碼的猛。

代碼解讀

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_7

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_1

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_2

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_3

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_4

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_5

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_二叉排序樹刪除操作代碼_代碼解讀_6

摘抄

概念

數(shù)據(jù)結(jié)構(gòu)_查找_二叉排序樹_概念

平衡二叉樹(AVL樹)

概念

平衡二叉樹

平衡二叉樹(Self-Balancing Binary Search Tree 或 Height-Balanced Binary Search Tree),
是一種二叉排序樹想虎,其中每一個結(jié)點的左子樹和右子樹的高度差至多等于1卦尊。

平衡因子

平衡二叉樹上的結(jié)點的左子樹減去右子樹的得到的差值,叫做平衡因子(Balance Factor)舌厨。

平衡因子可能的值是 -1岂却,0 和 1。

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_平衡因子

書中認為圖3中邓线,結(jié)點58的左子樹的高度是2淌友,我認為是3。

最小不平衡子樹

距離插入結(jié)點最近的骇陈、平衡因子的絕對值大于 1 的結(jié)點為根的子樹震庭,叫做最小不平衡子樹。

什么叫插入結(jié)點你雌?是指插入新結(jié)點的那個位置嗎器联?

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_最小不平衡子樹

結(jié)點58的左子樹的高度二汛,我認為是3。

平衡二叉樹實現(xiàn)算法代碼

旋轉(zhuǎn)操作

樹的結(jié)點結(jié)構(gòu)

typedef struct BiTNode
{
    int data;
    int bf;     // 結(jié)點的平衡因子
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

右旋轉(zhuǎn)操作代碼

void R_Rotate(BiTree *p)
{
    BiTree L;
    L = (*p)->lchild;   // L指向p的左子樹根結(jié)點
    (*p)->lchild = L->rchild;   // L的右子樹掛結(jié)為p的左子樹
    L->rchild = (*p);
    *p = L;     // P指向新的根結(jié)點
}

左旋操作代碼

void L_Rotate(BiTree *p)
{
    BiTree R;
    R = (*p)->rchild;   // R指向p的右子樹根結(jié)點
    (*p)->rchild = R->lchild;   // R的左子樹掛接為p的右子樹
    R->lchild = (*p);
    *p = R;     // p指向新的根結(jié)點
}

理解不了拨拓。按照我的思路肴颊,pR->lchild 的左子樹,可是這和左旋轉(zhuǎn)
后的結(jié)果不吻合渣磷。

重新畫了幾次婿着,根據(jù)代碼,可以得到預期效果圖了醋界【顾危可是,L 的右子樹為何
會變成 p 的左子樹形纺?

旋轉(zhuǎn)操作的關(guān)鍵在于:第一步的時候丘侠,原樹拆成了兩棵樹。旋轉(zhuǎn)過程見紙質(zhì)筆記逐样。

左平衡旋轉(zhuǎn)處理函數(shù)代碼

代碼
#define LH +1;      // 左高
#define EH 0;       // 等高
#define RH -1;      // 右高
void LeftBalance(BiTree *T)
{
    BiTree L, Lr;
    L = (*T)->lchild;       // L指向T的左子樹根結(jié)點
    switch(L->bf){
        case LH:
            /*1*/ (*T)->bf = L->bf = EH;
            R_Rotate(T);
            break;
        case RH:
            Lr = L->rchild;     // Lr指向T的左孩子的右子樹的根
            switch(Lr->bf){     // 修改T及其左孩子的平衡因子
                case LH:
                    (*T)->bf = RH;
                    L->bf = EH;
                    break;
                case EH:
                    (*T)->bf = L->bf = EH;
                    break;
                case RH:
                    (*T)->bf = EH;
                    L->bf = LH;
                    break;
            }
            Lr->bf = EH;
            L_Rotate(&(*T)->lchild);    // 對T的左子樹作左旋平衡處理
            R_Rotate(T);    // 對T做右旋平衡處理
    }
}
代碼解讀
數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_最小不平衡子樹_左平衡旋轉(zhuǎn)處理函數(shù)代碼_代碼解讀_1

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_最小不平衡子樹_左平衡旋轉(zhuǎn)處理函數(shù)代碼_代碼解讀_2

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_最小不平衡子樹_左平衡旋轉(zhuǎn)處理函數(shù)代碼_代碼解讀_3

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_最小不平衡子樹_左平衡旋轉(zhuǎn)處理函數(shù)代碼_代碼解讀_4

主函數(shù)代碼

代碼
Status InsertAVL(BiTree *T, int e, Status *taller)
{
    if(!T){
        *T = (BiTree)malloc(sizeof(BiTNode));
        (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->bf = EH;
        *taller = TRUE;
    }else{
        if(e = (*T)->data){
            *taller = FALSE;
            return FALSE;
        }
        if(e <(*T)->data){
            if(!InsertAVL(&(*T)->lchild, e, taller)){
                return FALSE;
            }
            if(taller){
                switch((*T)->bf){
                    case LH:
                        LeftBalance(T);
                        *taller = FALSE;
                        break;
                    case EH:
                        (*T)->bf = LH;
                        *taller = TRUE;
                        break;
                    case RH:
                        (*T)->bf = EH;
                        *taller = FALSE;
                        break;
                }
            }
        }else{
            if(!InsertAVL(&(*T)->rchild, e, taller)){
                return FALSE;
            }
            if(*taller){
                switch((*T)->bf){
                    case LH:
                        (*T)->bf = EH;
                        *taller = FALSE;
                        break;
                    case EH:
                        (*T)->bf = RH;
                        *taller = TRUE;
                        break;
                    case RH:
                        RightBalance(T);
                        *taller = FALSE;
                        break;
                }
            }
        }
    }
    
    return TRUE;
}
代碼解讀

《大話數(shù)據(jù)結(jié)構(gòu)》中的代碼蜗字,好像有很多錯誤,只可以當作逼真的偽代碼去看待脂新。

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_平衡二叉樹實現(xiàn)算法代碼_代碼解讀_1

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_平衡二叉樹實現(xiàn)算法代碼_代碼解讀_2

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_平衡二叉樹實現(xiàn)算法代碼_代碼解讀_3

數(shù)據(jù)結(jié)構(gòu)_查找_平衡二叉樹(AVL樹)_平衡二叉樹實現(xiàn)算法代碼_代碼解讀_4

多路查找樹(B樹)

摘抄

必要性

要操作的數(shù)據(jù)非常大挪捕,大到無法在內(nèi)存中處理。

定義

多路查找樹(multi-way search tree)的每一個結(jié)點的孩子數(shù)可以多于兩個戏羽,且每一個結(jié)點
處可以存儲多個元素担神。元素之間存在某種特定的排序關(guān)系。

2-3樹

概念
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_概念_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_概念_2
2-3樹的插入實現(xiàn)
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_插入_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_插入_2

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_插入_3

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_插入_4
2-3樹的刪除實現(xiàn)
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_2

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_3

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_4

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_5

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_6

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_7

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_23樹_刪除_8

可以理解這些方法能夠保證刪除的元素在被刪除后始花,新樹仍然是2-3樹妄讯,但不明白這么做的規(guī)律性,
更無能力用代碼實現(xiàn)刪除操作酷宵。

2-3-4樹

概念
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_234樹_概念
2-3-4樹的插入和刪除
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_234樹_插入刪除_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_234樹_插入刪除_2

B樹

概念與性質(zhì)
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B樹_概念與性質(zhì)_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B樹_概念與性質(zhì)_2
減少內(nèi)存與外存交換數(shù)據(jù)的頻率的原因
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B樹_減少內(nèi)存與外存交換數(shù)據(jù)的頻率的原因_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B樹_減少內(nèi)存與外存交換數(shù)據(jù)的頻率的原因_2

B+樹

產(chǎn)生原因--優(yōu)化B樹
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B加樹_產(chǎn)生原因
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B加樹_產(chǎn)生原因
概念
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B加樹_概念_1

數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B加樹_概念_2
與B樹的對比
數(shù)據(jù)結(jié)構(gòu)_查找_多路查找樹_B加樹_與B樹的對比

散列查找表概述

摘抄

定義

數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_定義_1

散列表查找步驟

1.存儲時亥贸,通過散列函數(shù)計算記錄的散列地址,并按該存儲地址存儲這條記錄浇垦。

2.查找時炕置,通過相同的散列函數(shù)計算記錄的散列地址,并按該散列地址讀取記錄男韧。

散列表適用場景

1.最適合的求解問題是查找與給定關(guān)鍵字等值的記錄朴摊。

2.同樣的關(guān)鍵字對應很多記錄的問題,不適合用散列表查找此虑。

3.范圍查找甚纲,不適合用散列表查找。

沖突

數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_沖突

散列函數(shù)的構(gòu)造方法

設計好的散列函數(shù)的原則

1.計算簡單朦前。

2.散列地址分布均勻介杆。這和“使用連續(xù)的存儲空間存儲記錄”有關(guān)嗎鹃操?

直接定址法
概念
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_直接定址法_概念
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_直接定址法_概念
優(yōu)缺點
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_直接定址法_優(yōu)缺點
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_直接定址法_優(yōu)缺點
數(shù)字分析法
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_數(shù)字分析法

只強調(diào)了抽取,對散列函數(shù)并無固定要求春哨。

平方取中法
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_平方取中法
折疊法
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_折疊法

存儲標簽id時荆隘,我常用的方法是,存儲“1,2,3,4”這樣的字段赴背。有人提出椰拒,
計算這4個標簽ID的“位運算”,存儲“位運算”的結(jié)果凰荚。具體應用方法已經(jīng)
忘記耸三。這也是折疊法。它們都減少了占用的存儲空間浇揩。

除留余數(shù)法
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_除留余數(shù)法_1
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_除留余數(shù)法_2
隨機數(shù)法
數(shù)據(jù)結(jié)構(gòu)_查找_散列查找表概述_摘抄_隨機數(shù)法

處理散列沖突的方法

摘抄

開放定址法

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_開放定址法_1

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_開放定址法_2

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_開放定址法_3

再散列函數(shù)法

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_再散列函數(shù)法

存儲的時候,是否應該記錄解決沖突使用的散列函數(shù)憨颠?若不記錄胳徽,讀取
數(shù)據(jù)的時候,如何計算存儲時候的地址爽彤?

鏈接地址法

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_鏈接地址法_1

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_鏈接地址法_1

公共溢出法

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_公共溢出法_1

數(shù)據(jù)結(jié)構(gòu)_查找_處理散列沖突的方法_摘抄_公共溢出法_2

散列表查找實現(xiàn)

代碼

散列表結(jié)構(gòu)

#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12
#define NULLKEY -32768
typedef struct 
{
    int *elem;      // 數(shù)據(jù)元素存儲基址
    int count;      // 當前數(shù)據(jù)元素個數(shù)
}HashTable;
int m = 0;          // 散列表表長养盗,全局變量

散列表初始化

Status InitHashTable(HashTable *H)
{
    int i;
    m = HASHSIZE;
    H->count = m;
    H->elem = (int *)malloc(m*sizeof(int));
    for(i = 0; i < m; i++){
        H->elem[i] = NULLKEY;
    }
    return OK;
}

散列函數(shù)

int Hash(int key)
{
    return key % m;
}

插入操作

void InsertHash(HashTable *H, int key)
{
    int addr = Hash(key);       // 求散列地址
    while(H->elem[addr] != NULLKEY)
        addr = (addr + 1) % m;
    H->elem[addr] = key;
}

查詢操作

void SearchHash(HashTable *H, int key)
{
    int addr = Hash(key);
    while(H->elem[addr] != key){
        addr = (addr + 1) % m;
        if(H->elem[addr] != key  || addr == Hash(key))
        {
            return UNSUCCESS;
        }
    }
    return SUCCESS;
}

if(H->elem[addr] != key || addr == Hash(key)) 中的 addr == Hash(key) 說明
循環(huán)回到原點,我不理解這點适篙。

if(H->elem[addr] != key  || addr == Hash(key))
{
    return UNSUCCESS;
}

這塊代碼是否有問題往核?

H->elem[addr] != key 成立時,應該繼續(xù)計算哈希地址嚷节。

散列表查找性能分析

數(shù)據(jù)結(jié)構(gòu)_查找_散列表查找實現(xiàn)_摘抄_散列表查找性能分析_1

數(shù)據(jù)結(jié)構(gòu)_查找_散列表查找實現(xiàn)_摘抄_散列表查找性能分析_2

喜歡我的文章請關(guān)注公眾號 ganggangwudao 或掃描個人主頁的微信二維碼聂儒,謝謝!

我篤信“寫作可以促進思考”硫痰,會以自己面臨的問題為思考素材衩婚,寫成文字,堅持每天推文效斑。

如果可以和大家共同探討非春,就更開心了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缓屠,一起剝皮案震驚了整個濱河市奇昙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敌完,老刑警劉巖储耐,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蠢挡,居然都是意外死亡弧岳,警方通過查閱死者的電腦和手機凳忙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禽炬,“玉大人涧卵,你說我怎么就攤上這事「辜猓” “怎么了柳恐?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長热幔。 經(jīng)常有香客問我乐设,道長,這世上最難降的妖魔是什么绎巨? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任近尚,我火速辦了婚禮,結(jié)果婚禮上场勤,老公的妹妹穿的比我還像新娘戈锻。我一直安慰自己,他們只是感情好和媳,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布格遭。 她就那樣靜靜地躺著,像睡著了一般留瞳。 火紅的嫁衣襯著肌膚如雪拒迅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天她倘,我揣著相機與錄音璧微,去河邊找鬼。 笑死硬梁,一個胖子當著我的面吹牛往毡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播靶溜,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼开瞭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了罩息?” 一聲冷哼從身側(cè)響起嗤详,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓷炮,沒想到半個月后葱色,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡娘香,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年苍狰,在試婚紗的時候發(fā)現(xiàn)自己被綠了办龄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡淋昭,死狀恐怖俐填,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翔忽,我是刑警寧澤英融,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站歇式,受9級特大地震影響驶悟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜材失,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一痕鳍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧龙巨,春花似錦额获、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耘眨。三九已至昼榛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間剔难,已是汗流浹背胆屿。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留偶宫,地道東北人非迹。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像纯趋,于是被迫代替她去往敵國和親憎兽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 第一章 緒論 什么是數(shù)據(jù)結(jié)構(gòu)吵冒? 數(shù)據(jù)結(jié)構(gòu)的定義:數(shù)據(jù)結(jié)構(gòu)是相互之間存在一種或多種特定關(guān)系的數(shù)據(jù)元素的集合纯命。 第二章...
    SeanCheney閱讀 5,760評論 0 19
  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結(jié)點至多有m個孩子。 除根結(jié)點和葉子結(jié)點外痹栖,其它每個結(jié)點至少有m...
    文檔隨手記閱讀 13,201評論 0 25
  • 一亿汞、相關(guān)定義 查找——查找就是根據(jù)給定的某個值,在查找表中確定一個其關(guān)鍵字等于給定值的數(shù)據(jù)元素(或記錄)揪阿。所有這些...
    開心糖果的夏天閱讀 1,118評論 0 8
  • 因為之前就復習完數(shù)據(jù)結(jié)構(gòu)了疗我,所以為了保持記憶咆畏,整理了一份復習綱要,復習的時候可以看著綱要想具體內(nèi)容吴裤。 樹 樹的基本...
    牛富貴兒閱讀 6,840評論 3 10
  • 信息來源:wind陸家嘴早餐/一張圖研報/羅博白蔡燉資管/蔡行之友金融服務平臺/未名宏觀研究 1.基本面+海外 ◆...
    阿泰想自由閱讀 247評論 0 0