堆的应用
对于堆的应用,我最熟悉的例子就是堆排序了(以升序排列为例)。算法思想:建立大根堆,每次取出根结点,与最后一个叶子节点就行交换,然后维持大根堆;依次递归实现堆排序。如下描述:
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;
}