1. 程式人生 > >高階資料結構的學習與實現之 Trie樹,字典樹

高階資料結構的學習與實現之 Trie樹,字典樹

第一次自學一種新的資料結構,感覺學會利用資源很重要,參考別人寫的部落格,谷歌搜尋一下關於這中資料結構的一些問題,解決等,學會搜尋資料,學習並掌握一門資料結構並不是很難。

要知道相關的基本知識,主要應用與哪一方面,還有它的具體實現是如何的。

在編碼的時候還是會遇到各種問題,需要認真解決。總體來說學習得還是比較成功得,也掌握了它的使用。

一、分析題目要求

(一)程式設計的任務:

學習一種課外的資料結構,並實現它。包括:1)初始化2)插入元素3)刪除元素4)查詢元素5)相關應用

本程式實現了以上5個要求,實驗報告是根據Trie樹的學習與實現過程而寫的。

(二)函式規定

·Trie CreateTrieNode()

1) 建立Tire樹 

引數       :無     

返回值     :Trie 已初始化的TrieNode節點指標

2) 輸入的形式 :無

輸入值的範圍:無

3) 輸出的形式 :無

4) 所能達到的功能:

用於建立Trie節點,初始化count0existfalse,子節點為NULL 

·void InsertTrieNode(Trie root , char *word)

1) 插入單詞元素

引數       :Trie 指定節點

word 指定單詞字串   

返回值     :無

2) 輸入的形式 :字串型別

輸入值的範圍:字串範圍

3) 輸出的形式 :無

4) 所能達到的功能:

用於向指定節點插入指定字串節點

·bool SearchString(Trie root , char* word)

1) 查詢字串 

引數       :Trie 指定節點

word 指定單詞字串     

返回值     :bool 是否存在指定字串

2) 輸入的形式 :字串型別

輸入值的範圍:字串範圍

3) 輸出的形式 :無

4) 所能達到的功能:

用於在指定根節點中查詢字串是否存在

·int SearchTrieNode(Trie root , char* word)

1) 查詢單詞前綴出現的次數 

引數       :Trie 指定節點

word 指定單詞字串     

返回值     :int 

單詞前綴出現的次數

2) 輸入的形式 :字串型別

輸入值的範圍:字串範圍

3) 輸出的形式 :無

4) 所能達到的功能:

用於在指定根節點中查詢單詞字首次數,類似SearchString

·bool DelectString(Trie root , char* word)

1) 刪除指定單詞 

引數       :Trie 指定節點

word 指定單詞字串  

返回值     :bool 刪除成功與否

2) 輸入的形式 :字串型別

輸入值的範圍:字串範圍

3) 輸出的形式 :無

4) 所能達到的功能:

用於在指定根節點中刪除指定單詞

·void DelectTrie(Trie root)

1) 刪除整棵樹

引數       :Trie 指定字典樹

返回值     :無

2) 輸入的形式 :Trie結構指標

輸入值的範圍:無

3) 輸出的形式 :無

4) 所能達到的功能:

因為現實中刪除某個元素的情況較少見,而刪除整棵樹較為常見,

        因此提供刪除整棵樹的方法,用於釋放整個字典樹佔的堆空間

·void TraverTrie(Trie root)

1) 遍歷整個字典樹

引數       :Trie 指定字典樹

返回值     :無

2) 輸入的形式 :Trie結構指標

輸入值的範圍:無

3) 輸出的形式 :字串型別

4) 所能達到的功能:

輸出字典樹中的每一個單詞

·void introdution()

1) 遍歷整個字典樹

引數       :無

返回值     :無

2) 輸入的形式 :無

輸入值的範圍:無

3) 輸出的形式 :字串型別

4) 所能達到的功能:

這是一個輸出頂部介紹的函式,因為不想在這裡打太多程式碼,

所以使用了巨集定義,具體程式碼包含在head.h的標頭檔案中。

·void memu()

1) 輸出選單的函式

引數       :無

返回值     :無

2) 輸入的形式 :無

輸入值的範圍:無

3) 輸出的形式 :字串型別

4) 所能達到的功能:

使用了巨集定義,包含在head.h

·void working()

1) 主要工作的函式

引數       :無

返回值     :無

2) 輸入的形式 :int整型,char字元型別,string字串型別

輸入值的範圍:int 2147483647~-2147483648char -128~127

3) 輸出的形式 :字串型別

4) 所能達到的功能:

主函式的執行主要在此,但在主函式裡面呼叫此函式即可,

        用於完成增刪查改

·int main()

1) 主函式

引數       :無

返回值     :int 

2) 輸入的形式 :無

輸入值的範圍:無

3) 輸出的形式 :字串型別

4) 所能達到的功能:

程式的入口,分別呼叫其他函式以實現其功能

二、解題思路

Trie樹的資料結構:

typedef struct TrieNode

{

    int count;                  //用來統計單詞前綴出現的次數

    struct TrieNode* next[26];  //指向各個子樹的指標

    bool exist;                 //標記該節點處是否構成單詞

    char trans[11];             //當前節點對應的單詞

}TrieNode ,*Trie;

1)初始化:

在記憶體申請一塊Trie樹的指標空間,把初始值設為0

2)插入元素:

對於一個單詞,從根開始,沿著單詞的各個字母所對應的樹中的節點分支向下走, 直到單詞遍歷完,將最後的節點的exist標記為true,表示該單詞已插入Trie樹。

 while(字串未結束)

    {

        if(當前位置為空)

        {

            位當前元素申請空間;

        }

        指標指向當前元素;

        為當前元素賦值

        字串向下移

}

3)刪除元素:

對於一個單詞,判斷是否存在字典樹中,不存在即返回;

存在分是否為字串的字首,以遞迴的形式進行刪除

1不是->遍歷整個單詞,釋放記憶體空間

2->遍歷,把count1,知道末尾把exist設為false

while(字串未結束)

    {

        if(當前節點為空)

            return false

        else if(非字首)

        {

            free(當前空間)

        }

        else

        {

           count--

           free(最後一個結點);

        }

        字串指標向下移

}

4)查詢元素:

從根開始按照單詞的字母順序向下遍歷trie樹,一旦發現某個節點標記不存在或者單詞遍歷完成而最後的節點的existfalse,則表示該單詞不存在,若最後的節點標記為true,表示該單詞存在。

while(字串未結束)

    {

        f(當前節點為空)

            return 不存在;

        指向下一個節點

        字串指標向下移

    }

    return (節點的->exist);

5)相關應用:

字首查詢的典型應用

很多單詞(只有小寫字母組成,不會有重複的單詞出現),現在要統計出以某個字串為字首的單詞數量

開始,初始化一棵字典樹,然後不斷輸入單詞,即想樹插入元素。然後即可呼叫

int SearchTrieNode(Trie root , char* word) 函式獲取字首個數。

三、除錯分析

(一)問題討論與分析

在此過程中,遇到

1) codeblocks 編譯器在編譯的時候並不會認出單詞拼錯這種錯誤,不像java的編譯器那麼智慧,所以有一個單詞拼錯了,然後我找了好久的錯誤才發現,記得之前也遇到過這種情況,也是找了好久才找出錯誤。解決:細心打程式碼,或者換一個編譯器。

2) 在實現刪除的時候,發現刪除不了,有一個問題是字串用錯個,只因拷貝時沒改,還有一個是free函式問題,指標的記憶體空間釋放後並不會指向NULL,而是指向任一不確定位置,所以我再查詢時還是發現找得到它。解決:使用free函式後,在把指標指向NULL

3) 遍歷整棵字典樹時,不知道要遍歷每一個字元還是字串,最後考慮到基本元素為字串後,就通過遞迴方式遍歷整棵樹。

(二)測試(多組)

 *****************************************************************************

                                ●新建一棵字典樹

                                ●插入新單詞

                                ●查詢單詞

                                ●刪除單詞

                                ●刪除整個字典樹

                                ●查詢字首個數

                                ●檢視所有單詞

                                ●退出

 *****************************************************************************

測試樣例一:

輸入

1

2

aa

2

a

3

a

4

aa

7

6

aa

6

a

0

輸出

Before Init...

Init Success!

插入成功!

插入成功!

字串【a】存在字典樹中

字串【aa】刪除成功

--------------a

字首【aa】不存在字典樹中

字首【a】存在字典樹中出現[1]

測試樣例二:

輸入

1

2

abc

2

aaa

2

guo

2

gui

2

nan

7

6

a

3

ggg

3

guo

4

abc

7

5

確定

Y

0

輸出:

Before Init...

Init Success!

插入成功!

插入成功!

插入成功!

插入成功!

插入成功!

--------------aaa

--------------abc

--------------gui

--------------guo

--------------nan

字首【a】存在字典樹中出現[2]

字串【ggg】不存在字典樹中

字串【guo】存在字典樹中

--------------aaa

--------------gui

--------------guo

--------------nan

字典樹刪除成功

測試樣例三:

輸入

1

2

data

2

struct

2

trie

3

trie

3

tire

4

trie

6

da

7

0

輸出:

Before Init...

Init Success!

插入成功!

插入成功!

插入成功!

字串【trie】存在字典樹中

字串【tire】不存在字典樹中

字串【trie】刪除成功

字首【da】存在字典樹中出現[1]

--------------data

--------------struct

(三)演算法的效率分析和改進設想

 

Trie樹的根結點不包含任何資訊,第一個字串為"abc",第一個字母為'a',因此根結點中陣列next下標為'a'-97的值不為NULL,其他同理,構建的Trie樹如圖所示,紅色結點表示在該處可以構成一個單詞。

很顯然,如果要查詢單詞"abc"是否存在,查詢長度則為O(len)len為要查詢的字串的長度。而若採用一般的逐個匹配查詢,則查詢長度為O(len*n)n為字串的個數。顯然基於Trie樹的查詢效率要高很多。 

如上圖中:Trie樹中存在的就是abcabbddda四個單詞。在實際的問題中可以將標記顏色的標誌位改為數量count等其他符合題目要求的變數。 已知n個由小寫字母構成的平均長度為10的單詞,判斷其中是否存在某個串為另一個串的字首子串。下面對比3 方法: 1、 最容易想到的:即從字串集中從頭往後搜,看每個字串是否為字串集中某個字串的字首,複雜度為O(n^2)。 

2、 使用hash:我們用hash存下所有字串的所有的字首子串。建立存有子串hash的複雜度為O(n*len)。查詢的複雜度為O(n)* O(1)= O(n)。 

3、 3、 使用Trie:因為當查詢如字串abc是否為某個字串的字首時,顯然以bcd....等不是以a開頭的字串就不用查找了,這樣迅速縮小查詢的範圍和提高查詢的針對性。所以建立Trie的複雜度為O(n*len),而建立+查詢在trie中是可以同時執行的,建立的過程也就可以成為查詢的過程,hash就不能實現這個功能。所以總的複雜度為O(n*len),實際查詢的複雜度只是O(len)

(四)經驗和體會

Trie樹的基本性質:

1)根節點不包含字元,除根節點意外每個節點只包含一個字元。2)從根節點到某一個節點,路徑上經過的字元連線起來,為該節點對應的字串。3)每個節點的所有子節點包含的字串不相同。

Trie的核心思想是空間換時間。利用字串的公共字首來降低查詢時間的開銷以達到提高效率的目的。

缺點:

Trie樹的記憶體消耗非常大.當然,或許用左兒子右兄弟的方法建樹的話,可能會好點.

四、附錄

(一)標頭檔案

#ifndef TEST_H_INCLUDED

#define TEST_H_INCLUDED

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <conio.h>

#include<windows.h>

#define henggang cout << " " ;for(int i =0;i<77;i++)cout << "-" ;

#define henggang1 for(int i =0;i<77;i++)cout << " " ;

#define xingxing cout << " " ;for(int i =0;i<77;i++)cout << "*" ;

#define kongge1 for(int i =0;i<6;i++)cout << " " ;

#define kongge2 for(int i =0;i<20;i++)cout << " " ;

#define kongge3 for(int i =0;i<30;i++)cout << " " ;

#define shuxian cout<< "|";

#define dingyi0 "Trie 字典樹的應用"

#define dingyi1 "Trie樹,又稱單詞查詢樹或鍵樹,是一種樹形結構,是一種雜湊樹的變種。"

#define dingyi2 "典型應用是用於統計和排序大量的字串(但不僅限於字串),所以經 "

#define dingyi3 "常被搜尋引擎系統用於文字詞頻統計。                               "

#define dingyi4 "優點是:最大限度地減少無謂的字串比較,查詢效率比雜湊表高。     "

#define checkTrie if(root==NULL){printf("請建立一棵字典樹\n");break;}

#define caidan cout<< "\n\t\t\t\t新建一棵字典樹\n\t\t\t\t插入新單詞\n\t\t\t\t查詢單詞\n\t\t\t\t刪除單詞\n\t\t\t\t刪除整個字典樹\n\t\t\t\t查詢字首個數\n\t\t\t\t檢視所有單詞\n\t\t\t\t退出\n";

#endif

(二)主程式

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "head.h"

using namespace std;

typedef struct TrieNode

{

    int count;                  //用來統計單詞前綴出現的次數

    struct TrieNode* next[26];  //指向各個子樹的指標

    bool exist;                 //標記該節點處是否構成單詞

    char trans[11];             //當前節點對應的單詞

}TrieNode ,*Trie;

/*

    建立Tire

        用於建立Trie節點,初始化count0existfalse,子節點為NULL

    引數      :無

    返回值    :Trie 已初始化的TrieNode節點指標

*/

Trie CreateTrieNode()

{

    TrieNode* tnode = (TrieNode *)malloc(sizeof(TrieNode));

    tnode->count    = 0;

    tnode->exist    = false;

    memset(tnode->next,0,sizeof(tnode->next));

    return tnode;

}

/*

    插入單詞元素

        用於向指定節點插入指定字串節點

    引數      :Trie 指定節點

              :word 指定單詞字串

    返回值    :無

*/

void InsertTrieNode(Trie root , char *word)

{

    if(root==NULL)return ;

    if(word==NULL)return ;

    Trie node   = root;

    char* p     = word;

    int id;

    while(*p)

    {

        id = *p-'a';

        if(node->next[id]==NULL)

        {

            node->next[id] = CreateTrieNode();

        }

        node = node->next[id];

        node->count     += 1;

        p++;

    }

    node->exist = true;

    if(strcpy(node->trans , word)!=NULL)

    cout <<"插入成功!\n";

}

/*

    查詢字串

        用於在指定根節點中查詢字串是否存在

    引數      :Trie 指定節點

              :word 指定單詞字串

    返回值    :bool 是否存在指定字串

*/

bool SearchString(Trie root , char* word)

{

    if(root==NULL)return false;

    if(word==NULL)return false;

    Trie node   = root;

    char* p     = word;

    int id;

    while(*p)

    {

        id = *p-'a';

        if(node->next[id]==NULL)

            return false;

        node = node->next[id];

        p++;

    }

    return (node->exist);

}

/*

    查詢單詞前綴出現的次數

        用於在指定根節點中查詢單詞字首次數,類似SearchString

    引數      :Trie 指定節點

              :word 指定單詞字串

    返回值    :int 單詞前綴出現的次數

*/

int SearchTrieNode(Trie root , char* word)

{

    if(root==NULL)return 0;

    if(word==NULL)return 0;

    char* p     = word;

    Trie node   = root;

    int id;

    while(*p)

    {

        id = *p-'a';

        if(node->next[id]==NULL)

            return 0;

        node = node->next[id];

        p++;

    }

    return node->count;

}

/*

    刪除指定單詞

        用於在指定根節點中刪除指定單詞

    引數      :Trie 指定節點

              :word 指定單詞字串

    返回值    :bool 刪除成功與否

*/

bool DelectString(Trie root , char* word)

{

    if(!SearchString(root,word))

        return false;

    char* str   = word;

    int id      = *str-'a';

    int len     = strlen(str),i=0;

    Trie p      = root;

    Trie q      = p->next[id];

    while(*str)

    {

        if(q==NULL||q->count==0)

            return false;

        else if(q->count==1)

        {

            p   = q;

            q   = q->next[*(str+1)-'a'];

            if(!i==len)

            {

                free(p);

                p   = NULL;

            }

            else

            {

                p->exist    = false;

                free(p->trans);

            }

            p->count=0;

        }

        else

        {

            p   = q;

            q   = q->next[*(str+1)-'a'];

            if(i==len-1)

            {

                p->exist    = false;

                free(p->trans);

            }

            p->count--;

        }

        str++;

        i++;

    }

    return true;

}

/*

    刪除整棵樹

        因為現實中刪除某個元素的情況較少見,而刪除整棵樹較為常見,

        因此提供刪除整棵樹的方法,用於釋放整個字典樹佔的堆空間

    引數      :Trie 指定字典樹

    返回值    :無

*/

void DelectTrie(Trie root)

{

    int i;

    for(i=0;i<26;i++)

    {

     if(root->next[i]!=NULL)

            DelectTrie(root->next[i]);

    }

    root->exist = false;

    free(root);

    root = NULL;

}

/*

    遍歷整個字典樹

        輸出字典樹中的每一個單詞

    引數      :Trie 指定節點

    返回值    :無

*/

void TraverTrie(Trie root)

{

    int i;

    for(i=0;i<26;i++)

    {

     if(root->next[i]!=NULL)

            TraverTrie(root->next[i]);

    }

    if(root->exist)

        printf("--------------%s\n",root->trans);

}

/*

    輸出頂部介紹

        這是一個輸出頂部介紹的函式,因為不想在這裡打太多程式碼,

        所以使用了巨集定義,具體程式碼包含在head.h的標頭檔案中。

    引數      :無

    返回值    :無

*/

void introdution()

{

    henggang;

    cout<< endl;

    shuxian kongge3 cout<< dingyi0;kongge3 shuxian

    cout<< endl;

    shuxian henggang1 shuxian

    cout<< endl;

    shuxian  kongge1 cout<< dingyi1; kongge1 shuxian

    cout<< endl;

    shuxian  kongge1 cout<< dingyi2; kongge1 shuxian

    cout<< endl;

    shuxian  kongge1 cout<< dingyi3; kongge1 shuxian

    cout<< endl;

    shuxian  kongge1 cout<< dingyi4; kongge1 shuxian

    cout<< endl;

    henggang

    cout<< endl;

}

/*

    輸出選單的函式

        使用了巨集定義,包含在head.h

    引數      :無

    返回值    :無

*/

void memu()

{

    xingxing

    caidan

    xingxing

    cout<< endl;

}

/*

    主要工作的函式

        主函式的執行主要在此,但在主函式裡面呼叫此函式即可,

        用於完成增刪查改

    引數      :無

    返回值    :無

*/

void working()

{

    Trie root = NULL;     // 字典樹的根節點

    char str1[300] , str2[30] , str3[30] , *p;

    int i , k;

    int chose;

    while(true)

    {

        memu();

        cout <<"請選擇要操作的序號,回車結束      ";

        cin>> chose;

        if(chose==0)

            break;

        switch(chose)

        {

            case 1:

                    cout <<"Before Init...\n";

                    Sleep(1000);

                    root = CreateTrieNode();

                    if(root==NULL)

                    {

                       cout <<"\t字典樹建立失敗\n";

                       exit(0);

                    }

                    cout <<"Init Success!\n";

                    break;

            case 2:

                    checkTrie

                    cout <<"請輸入需要插入的單詞,回車鍵結束        ";

                    getchar();

                    gets(str1);

                    if(str1!=NULL||str1!=" ")

                    {

                       InsertTrieNode(root,str1);

                    }

                    break;

            case 3:

                    checkTrie

                    cout <<"請輸入需要查詢的單詞,回車鍵結束        ";

                    getchar();

                    gets(str2);

                    if(str2!=NULL||str2!=" ")

                    {

                        if(SearchString(root,str2))

                        {

                            printf("字串【%s】存在字典樹中\n",str2);

                        }

                        else

                        {

                            printf("字串【%s】不存在字典樹中\n",str2);

                        }

                    }

                    else

                    {

                        cout <<"請按格式輸入!\n";

                    }

                    break;

            case 4:

                    checkTrie

                    cout <<"請輸入需要刪除的單詞,回車鍵結束        ";

                    getchar();

                    gets(str3);

                    if(str3!=NULL||str3!=" ")

                    {

                        if(DelectString(root,str3))

                        {

                            printf("字串【%s】刪除成功\n",str3);

                        }

                        else

                        {

                            printf("刪除失敗,字串【%s】不存在字典樹中\n",str3);

                        }

                    }

                    else

                    {

                            cout <<"請按格式輸入!\n";

                    }

                    break;

            case 5:

                    checkTrie

                    MessageBox(NULL, "此操作將無法撤銷\n(cannot be undone!)", "警告", MB_OK);//彈窗警告

                    cout <<"輸入Y確定,其他返回。     ";

                    char config;

                    getchar();

                    config = getchar();

                    getchar();

                    if(config=='Y')

                    {

                        DelectTrie(root);

                        if(root->next[1]==NULL)

                        {

                            cout <<"字典樹刪除成功\n";

                        }

                        else

                        {

                            cout <<"字典樹刪除失敗\n";

                        }

                    }

                    break;

            case 6:

                    checkTrie

                    cout <<"請輸入需要的字首,回車鍵結束        ";

                    getchar();

                    gets(str2);

                    if(str2!=NULL&&str2!=" ")

                    {

                        int count = SearchTrieNode(root,str2);

                        if(count>0)

                        {

                            printf("字首【%s】存在字典樹中出現[%d]\n",str2,count);

                        }

                        else

                        {

                            printf("字首【%s】不存在字典樹中\n",str2);

                        }

                    }

                    else

                    {

                            cout <<"請按格式輸入!\n";

                    }

                    break;

            case 7:

                    checkTrie

                    TraverTrie(root);

                    break;

            default:

                    printf("請按格式輸入!\n");

                    break;

        }

    }

}

/*

    主函式

        程式的入口,分別呼叫其他函式以實現其功能

    引數      :無

    返回值    :int 

*/

int main()

{

    introdution();//輸出頂部介紹

    working();      //主要執行函式

    cout<<"謝謝使用!\n";

    return 0;

}

=================================我是分割線=======================================

因為原始碼中有巨集定義,並且包含於標頭檔案中,這個懂C語言的基本知道如何使用,不行的話自行百度一下。

最後,如果對上面的某處有疑問,可以留言,一起討論學習,我會很樂意的。感謝博主hackbuteer1的一篇文章,此課程設計主要參考他寫的教程。

http://blog.csdn.net/hackbuteer1/article/details/7964147

還有
http://blog.csdn.net/hguisu/article/details/8131559

----------------------------------------------------------------------------------------------轉載無需註明出處-by guin_guo

相關推薦

高階資料結構學習實現 Trie字典

第一次自學一種新的資料結構,感覺學會利用資源很重要,參考別人寫的部落格,谷歌搜尋一下關於這中資料結構的一些問題,解決等,學會搜尋資料,學習並掌握一門資料結構並不是很難。 要知道相關的基本知識,主要應用與哪一方面,還有它的具體實現是如何的。 在編碼的時候還是會遇到各種問題,需

資料結構學習筆記——堆疊鏈式儲存結構(c語言實現

棧的鏈式儲存結構使用單鏈表實現,同線性表一樣,鏈式儲存結構的堆疊在儲存空間的利用上顯得更加靈活,只要硬體允許一般不會出現溢位的情況。但鏈式棧相對於順序棧稍顯麻煩,若所需堆疊空間確定,順序棧顯得方便一些。關於鏈式和順序式的選擇視具體情況而定。 1.棧的鏈式儲存結構

堆的python實現及其應用 資料結構--堆的實現深入分析

堆的概念 優先佇列(priority queue)是一種特殊的佇列,取出元素的順序是按照元素的優先權(關鍵字)大小,而不是進入佇列的順序,堆就是一種優先佇列的實現。堆一般是由陣列實現的,邏輯上堆可以被看做一個完全二叉樹(除底層元素外是完全充滿的,且底層元素是從左到右排列的)。 堆分為最大堆和最小堆,最大堆

資料結構學習——帶父節點的二叉搜尋全部功能c++實現

第二篇二叉樹我們帶來純c++版本的二叉搜尋樹,這篇程式碼是我學習了很多優秀程式碼之後寫出來的,大家在學習二叉搜尋樹的同時可以著重看下在這裡如何定義的二叉搜尋樹,以及Private和Public的封裝聯動,對程式碼思路是一個很好的提升。 注:在這裡的遍歷我只寫了前序遍歷,其他

資料結構--堆的實現深入分析

一,介紹 以前在學習堆時,寫了兩篇文章:資料結構--堆的實現(上)   和   資料結構--堆的實現(下),  感覺對堆的認識還是不夠。本文主要分析資料結構 堆(討論小頂堆)的基本操作的一些細節,比如 insert(插入)操作 和 deleteMin(刪除堆頂元素)操作的實現細節、分析建堆的時間複雜度、堆的

麻將查胡演算法 資料結構設計實現

根據前面一片部落格傳送門,演算法介紹,這裡來實現核心部分 中間用到的一些功能函式,大家自己搞定吧,我把核心演算法po出來大家參考 一、資料結構設計c# 演算法流程:輪流判斷每一張牌是否符合要求 找出所有可以當將的牌 while(將牌沒遍歷完) {  

資料結構java語言實現棧及其應用

 棧的結構比較簡單,跟連結串列差不多底層還是一個數組,程式碼實現也比較容易,主要利用的就是他的先進後出的特點,java程式碼如下: <span style="font-size:14px;">package Stack; /* * 棧的實現 * 基本思路還是

資料結構學習實驗指導》3-7:求字首表示式的值

實驗內容:計算字首表示式的值。 輸入說明:輸入一行不超過30個字元的字首表示式,只包含+、-、*、/以及運算數,不同物件之間用空格分隔。 輸出說明:輸出字首表示式的運算結果,精確到小數點後1位,或輸出錯誤資訊“ERROR“。 測試用例: 輸入 | 輸出

資料結構C語言實現鏈式佇列的6種演算法程式碼

#include <stdio.h>#include <stdlib.h>typedef int elemType;/************************************************************************//* 以下是關於佇列連

資料結構的Java實現(十)—— 二叉

目錄 樹 二叉樹 樹 樹(tree)是一種抽象資料型別(ADT),用來模擬具有樹狀結構性質的資料集合。它是由n(n>=0)個有限節點組成一個具有層次關係的集合。節點一般代表一些實體,在java中節點一般代表物件。連線節點的線稱為邊,一般從一個節點到另一個節點的唯

資料結構學習筆記——線性表順序表(c語言實現

1.概念 順序表即線性表的順序儲存結構 ,指的是用一段地址連續的儲存單元依次儲存線性表資料元素。線上性表中,每個資料元素的型別都相同,一般可以用一維陣列來實現順序儲存結構。 2.實現 (1)建立順序表的結構 利用c語言結構體來建立順序表的結構,順序表結構體中

Lucene學習筆記-核心資料結構PriorityQueue的實現原理

Luene的核心應用場景是全文檢索。簡單來說,就是通過使用者輸入的關鍵詞來匹配相關文件,然後根據匹配程度返回TopN的查詢結果給使用者。 這裡需要解決的一個核心問題就是如何快速返回TopN的結果,這本質上是一個排序的問題。說起排序,我們有很多選擇,冒泡,快排,歸併...。 這些排序演算法在資料量小的時候,不是

資料結構學習路4 佇列的基本操作(順序儲存的迴圈佇列+連結串列實現

佇列先進先出,這裡用了順序(陣列)和鏈式兩種方式實現,下次再用鏈式儲存實現以下堆疊試試 迴圈佇列: //順序儲存結構的迴圈佇列 #include<iostream> using namespace std; #define MAXSIZE 100 typedef

資料結構學習鏈佇列c++實現楊輝三角

#ifndef LINKQUEUE_H #define LINKQUEUE_H #include <iostream> #include <assert.h> using namespace std; template <class T>

資料結構學習筆記(四) 圖鄰接表實現深度優先遍歷

一下是使用鄰接表儲存表示,實現圖的深度優先遍歷的示例。 用於遍歷的有向圖如下: #include<iostream> #define MaxVertexNum 6 using namespace std; //抽象資料型別 typedef c

資料結構學習路(一)C語言對陣列的簡單實現

以下的程式只是在觀看郝斌老師講解的(C語言資料結構)之後自己做得簡單練習。# include <stdio.h> # include <stdlib.h> typedef struct MyArray{ int * pBase; //存放陣列第一個

nginx 學習高階資料結構基數ngx_radix_tree_t

1 nginx的基數樹簡介 基數樹是一種二叉查詢樹,它具備二叉查詢樹的所有優點:檢索、插入、刪除節點速度快,支援範圍查詢,支援遍歷等。在nginx中僅geo模組使用了基數樹。nginx的基數樹使用ngx_radix_tree_t這個結構體表示的。ngx_radix_tree

資料結構學習筆記線性表

一、概念 什麼是線性表呢? 一個簡單的理解如下: 線性表是由稱為元素(Element)的資料項組成的一種有限且有序的序列 其中,這裡有一個需要注意的地方: 有序是指線性表中的每個元素都有自己的位置,而不是指線性表中的元素按某種順序排列 二、抽象資料型別定義 要給資料結構定

資料結構——排序查詢(2)——希爾排序(C++實現

希爾排序原理 希爾排序(Shell’s Sort),也稱為“縮小增量排序”,是一種插入排序類的演算法。最簡單的插入排序,我在上一個專欄的一篇文章C++抽象程式設計——演算法分析(8)——插入排序演算法與分析有提到過,這裡就不再贅述,這裡就只介紹一些我以前沒寫過的演算法。 希爾排序是一

資料結構——排序查詢(5)——折半查詢(C++實現)法

順序查詢 順序查詢,是一種最直觀的查詢方式。原理閒蕩簡單就是我們正常思維的查詢,從給定的序列出發,依次檢查序列中的每一個專案是否為我們給定的關鍵字。是則查詢成功,否則查詢失敗。 bool searchByOrder(vecter<int> vec){ for(int