diff --git a/thu_dsa/chp10/CompleteBinaryHeap.h b/thu_dsa/chp10/CompleteBinaryHeap.h new file mode 100644 index 0000000..065a9b9 --- /dev/null +++ b/thu_dsa/chp10/CompleteBinaryHeap.h @@ -0,0 +1,93 @@ +#ifndef COMPLETEBINARYHEAP_H_ +#define COMPLETEBINARYHEAP_H_ + +#include "../chp2/Vector.h" +#include "PriorityQueue.h" + +#define INHEAP(i) ((i >= 0) && (i < getSize())) +#define PARENT(i) ((i-1) >> 1) +#define LCHILD(i) ((i << 1) + 1) +#define RCHILD(i) ((i << 1) + 2) +#define HASPARENT(i) INHEAP(PARENT(i)) +#define HASLCHILD(i) INHEAP(LCHILD(i)) +#define HASRCHILD(i) INHEAP(RCHILD(i)) +#define LASTINTERNAL PARENT(size() - 1) + +template +class CBHeap: public Vector>, public PriorityQueue{ +protected: + //internal methods + void percolate_down(int pos); + void percolate_up(int pos); + int proper_parent(int pos); + +public: + //constructor + CBHeap() = default; + CBHeap(entry* src, int n); + + int size() { return getSize(); } + bool empty(){ return size() == 0; } + void insert(entry e); + void insert(K key, V value) { insert(entry(key, value)); } + entry getMax() { return _elem[0]; } + entry delMax(); + +}; + +//internal methods + +template +int CBHeap::proper_parent(int pos){ + if (!HASLCHILD(pos)) return pos; + if (!HASRCHILD(pos)) return get(pos) >= get(LCHILD(pos)) ? pos : LCHILD(pos); + int proper = get(pos) >= get(LCHILD(pos)) ? pos : LCHILD(pos); + return get(proper) >= get(RCHILD(pos)) ? proper : RCHILD(pos); +} + +template +void CBHeap::percolate_down(int pos){ + entry tmp = get(pos); + for(int p = proper_parent(pos); p != pos; p = proper_parent(pos)){ + get(pos) = get(p); + pos = p; + get(pos) = tmp; + } +} + +template +void CBHeap::percolate_up(int pos){ + entry tmp = get(pos); + while(HASPARENT(pos)){ + if(get(PARENT(pos)) >= tmp) break; + + get(pos) = get(PARENT(pos)); + pos = PARENT(pos); + } + get(pos) = tmp; +} + +//public methods + +template +CBHeap::CBHeap(entry* src, int n){ + copyfrom(src, 0, n); + for (int ix = LASTINTERNAL; ix >= 0; --ix) + percolate_down(ix); +} + +template +void CBHeap::insert(entry e){ + push_back(e); + percolate_up(getSize() - 1); +} + +template +entry CBHeap::delMax(){ + entry max = get(0); + _elem[0] = _elem[_size-- - 1]; + percolate_down(0); + return max; +} + +#endif diff --git a/thu_dsa/chp10/PriorityQueue.h b/thu_dsa/chp10/PriorityQueue.h new file mode 100644 index 0000000..e6311f2 --- /dev/null +++ b/thu_dsa/chp10/PriorityQueue.h @@ -0,0 +1,32 @@ +#ifndef PRIORITYQUEUE_H_ +#define PRIORITYQUEUE_H_ + +template +class entry{ +public: + K key; + V value; + + //constructor + entry() = default; + entry(K k, V v) : key(k), value(v) {} + + //overload operator + bool operator==(entry const e) { return key == e.key; } + bool operator!=(entry const e) { return key != e.key; } + bool operator>(entry const e) { return key > e.key; } + bool operator<(entry const e) { return key < e.key; } + bool operator>=(entry const e) { return (key > e.key) || (key == e.key); } +}; + +template +class PriorityQueue{ + virtual int size() = 0; + virtual bool empty() = 0; + virtual entry getMax() = 0; + virtual entry delMax() = 0; + virtual void insert(K key, V value) = 0; //duplicate keys are allowed + virtual void insert(entry e) = 0; +}; + +#endif diff --git a/thu_dsa/chp10/testHeap.cpp b/thu_dsa/chp10/testHeap.cpp new file mode 100644 index 0000000..174071e --- /dev/null +++ b/thu_dsa/chp10/testHeap.cpp @@ -0,0 +1,64 @@ +#include "CompleteBinaryHeap.h" +#include +#include +using std::cout; +using std::endl; + +void test_insert(); +void test_max(); +void test_heapify(); + +int main(){ + cout << "Running tests" << endl; + + test_heapify(); + test_insert(); + test_max(); + + cout << "All tests passed." << endl; + system("pause"); + return 0; +} + +void test_heapify(){ + int keys[] = { 5, 4, 7, 9, 1, 2, 8, 3, 6, 0 }; + int results[] = { 9, 6, 8, 5, 1, 2, 7, 3, 4, 0}; + entry src[10]; + for (int ix = 0; ix != 10; ++ix) + src[ix] = entry(keys[ix], 0); + CBHeap heap(src, 10); + assert(heap.size() == 10); + for (int ix = 0; ix != 10; ++ix) { + assert(heap[ix].key == results[ix]); + } +} + +void test_insert(){ + int keys[] = { 5, 4, 7, 9, 1, 2, 8, 3, 6, 0 }; + int results[] = { 9, 7, 8, 6, 1, 2, 5, 3, 4, 0 }; + CBHeap heap; + for(int ix = 0; ix != 10; ++ix){ + assert(heap.size() == ix); + heap.insert(entry(keys[ix], 0)); + } + for (int ix = 0; ix != 10; ++ix) + assert(heap[ix].key == results[ix]); +} + +void test_max(){ + int keys[] = { 5, 4, 7, 9, 1, 2, 8, 3, 6, 0 }; + entry src[10]; + for (int ix = 0; ix != 10; ++ix) + src[ix] = entry(keys[ix], 0); + CBHeap heap(src, 10); + for (int ix = 0; ix != 10; ++ix) { + assert(heap.size() == 10 - ix); + assert(heap.getMax().key == 9 - ix); + assert(heap.delMax().key == 9 - ix); + /* + for (int jx = 0; jx != 9 - ix; ++jx) + cout << heap[jx].key << " "; + cout << endl; + */ + } +} diff --git a/thu_dsa/hash.md b/thu_dsa/hash.md new file mode 100644 index 0000000..7557b3b --- /dev/null +++ b/thu_dsa/hash.md @@ -0,0 +1,14 @@ +Conclusions on Hashing +====================== + +## 散列函数的设计 +散列函数无非一个映射,其功能无非是将词条空间中的元素映射到散列表地址空间,其中前者远远大于后者,所以绝不可能是一个单射 +好的散列函数 + - 确定性:同一关键码总是被映射到同一地址 + - 快速 + - 满射:充分利用散列空间 + - 均匀:避免汇聚clustering。 +散列函数 + - 除余法 + - MAD法 + - 折叠法