堆和哈希表的實現與應用(二)

堆的應用

對於堆的應用,我最熟悉的例子就是堆排序了(以升序排列爲例)。算法思想:建立大根堆,每次取出根結點,與最後一個葉子節點就行交換,然後維持大根堆;依次遞歸實現堆排序。如下描述:

 

const int HEAP_SIZE = 1000;
const int MAXN = 100000;

template<class T>
void Max_Heap(T h[], int p, int heap_size)
{
    int tmp = h[p];
    for(int q = p << 1; q <= heap_size; q <<= 1)
    {
        if(q < heap_size && h[q] < h[q+1]) ++q;
        if(h[q] <= tmp) break;
        h[p] = h[q];
        p = q;
    }
    h[p] = tmp;
}

template<class T>
void Build_Max_Heap(T h[], int heap_size)
{
    for(int i = heap_size/2; i > 0; --i)
        Max_Heap(h, i, heap_size);
}

template<class T>
void HeapSort(T h[], int heap_size)
{
    Build_Max_Heap(h, heap_size);
    for(int i = heap_size; i > 1; --i)
    {
        swap(h[1], h[i]);
        Max_Heap(h, 1, i-1);
    }
}

 

以上是我對堆的一些理解;如有錯誤,請大家諒解。

下面讓我看看哈希表吧。對於哈希表我覺得自己沒有什麼發言權,請大家看看這個博客十一、從頭到尾徹底解析Hash 表算法,寫的特別的好。我就是從這篇博客學的哈希表。雖然沒有完全領悟,但是也瞭解了一二。

哈希表和堆的應用

例題:給大家一本英文小說,在所有的單詞中統計出前10個出現頻率最多的單詞。

 

/*
功能說明:統計一本書中各單詞的個數,打印出出現次數最多的前10個單詞
數據結構:哈希表、最小堆
*/

#include <iostream>
#include <fstream>
#include <cstring>
#include <cassert>
#include <cctype>

using namespace std;

const int HASH_SIZE = 87719;
const int WORD_SIZE = 30;

typedef struct node_hashTable *pstr_hashTable;
typedef struct node_heap *pstr_heap;

struct node_hashTable
{
    char *word;
    int Wcnt;
    pstr_hashTable next;
};

struct node_heap
{
    char word[WORD_SIZE];
    int Wcnt;
};

pstr_hashTable hashTable[HASH_SIZE];

int hash_function(const char *pstr)
{
    int value = 0;

    while(*pstr != '\0')
    {
        value = (value * 31 + *pstr++) % HASH_SIZE;
    }
    return value;
}

void appendWord_hashTable(const char *pstr)
{
    int index = hash_function(pstr);
    pstr_hashTable p = hashTable[index];

    if(p != NULL)
    {
        while(p != NULL)
        {
            if(0 == strcmp(pstr, p->word))
            {
                p->Wcnt++;
                return ;
            }
            p = p->next;
        }
        p = new node_hashTable;
        p->Wcnt = 1;
        p->word = new char[strlen(pstr) + 1];
        strcpy(p->word, pstr);
        p->next = NULL;
    }
    else
    {
        pstr_hashTable q = new node_hashTable;

        q->Wcnt = 1;
        q->word = new char[strlen(pstr) + 1];
        strcpy(q->word, pstr);
        hashTable[index] = q;
        hashTable[index]->next = NULL;
    }
}

void WriteToFile()
{
    FILE *fp = fopen("result.txt", "w");
    assert(fp);

    for(int i = 0; i < HASH_SIZE; ++i)
    {
        for(pstr_hashTable p = hashTable[i]; p != NULL; p = p->next)
        {
            fprintf(fp, "%s\t%d\n", p->word, p->Wcnt);
        }
    }
    fclose(fp);
}

void handle_word(char *str, int n)
{
    while (str[n] < '0' || (str[n] > '9' && str[n] < 'A') || (str[n] > 'Z' && str[n] < 'a') || str[n] > 'z')
    {
        str[n] = '\0';
        n--;
    }

    while (str[0] < '0' || (str[0] > '9' && str[0] < 'A') || (str[0] > 'Z' && str[0] < 'a') || str[0] > 'z')
    {
        int i = 0;
        while (i < n)
        {
            str[i] = str[i+1];
            i++;
        }
        str[i] = '\0';
        n--;
    }

    for(int i = 0; str[i] != '\0'; ++i)
    {
        if(str[i] >= 'A' && str[i] <= 'Z') str[i] = tolower(str[i]);
    }
}

void ShitDown(pstr_heap heap, int i, int heap_size)
{
    /*node_heap tmp;
    tmp.Wcnt = heap[p].Wcnt;
    memset(tmp.word, '\0', sizeof(char)*WORD_SIZE);
    strcpy(tmp.word, heap[p].word);

    for(int q = p << 1; p <= heap_size; q <<= 1)
    {
        if(q < heap_size && heap[q].Wcnt > heap[q + 1].Wcnt) q++;
        if(heap[q].Wcnt >= tmp.Wcnt) break;

        heap[p].Wcnt = heap[q].Wcnt;
        char tmpBuff[WORD_SIZE];
        memset(tmpBuff, '\0', sizeof(tmpBuff));
        strcpy(tmpBuff, heap[q].word);
        memset(heap[p].word, '\0', sizeof(char)*WORD_SIZE);
        strcpy(heap[p].word, tmpBuff);

        p = q;
    }
    heap[p].Wcnt = tmp.Wcnt;
    memset(heap[p].word, '\0', sizeof(char)*WORD_SIZE);
    strcpy(heap[p].word, tmp.word);
    */

    int min_index = -1;
    int left = 2 * i;
    int right = 2 * i + 1;

    if (left <= heap_size && heap[left].Wcnt < heap[i].Wcnt)
        min_index = left;
    else
        min_index = i;

    if (right <= heap_size && heap[right].Wcnt < heap[min_index].Wcnt)
        min_index = right;

    if (min_index != i)
    {
        swap(heap[i].Wcnt, heap[min_index].Wcnt);

        char buffer[WORD_SIZE];
        strcpy(buffer, heap[i].word);
        strcpy(heap[i].word, heap[min_index].word);
        strcpy(heap[min_index].word, buffer);

        ShitDown(heap, min_index, heap_size);
    }
}

void BuildMinHeap(pstr_heap heap, int heap_size)
{
    for(int i = heap_size/2; i > 0; --i)
        ShitDown(heap, i, heap_size);
}

void DestroyHashTable()
{
    for(int i = 0; i < HASH_SIZE; ++i)
        for(pstr_hashTable p = hashTable[i]; p != NULL; p = p->next)
        {
            delete [](p->word);
            delete p;
        }
}

int main()
{
    char str_word[WORD_SIZE];

    memset(str_word, '\0', sizeof(str_word));

    for(int i = 0; i < HASH_SIZE; ++i) hashTable[i] = NULL;

    FILE *book = fopen("book.txt", "r");
    assert(book);

    while(fscanf(book, "%s", str_word) != EOF)
    {
        int n = strlen(str_word) - 1;

        if(n >= 0)
           handle_word(str_word, n);

        appendWord_hashTable(str_word);
    }
    fclose(book);
    WriteToFile();

    int n = 10;
    pstr_heap MinHeap = new node_heap[n+1];
    int count = 0;

    FILE *fp_word = fopen("result.txt","r");
    assert(fp_word);

    for(int i = 1; i <= n; ++i)
    {
        fscanf(fp_word, "%s %d", str_word, &count);
        MinHeap[i].Wcnt = count;
        strcpy(MinHeap[i].word, str_word);
    }

    BuildMinHeap(MinHeap, n);

    while(fscanf(fp_word, "%s %d", str_word, &count) != EOF)
    {
        if(count > MinHeap[1].Wcnt)
        {
            MinHeap[1].Wcnt = count;
            memset(MinHeap[1].word, '\0', sizeof(char)*WORD_SIZE);
            strcpy(MinHeap[1].word, str_word);

            ShitDown(MinHeap, 1, n);
        }
    }
    fclose(fp_word);

    for(int i = 1; i <= n; ++i)
        cout << MinHeap[i].word << '\t' << MinHeap[i].Wcnt << endl;

    DestroyHashTable();

    return 0;
}



 

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