complete the coding of complete binary heap, with all tests passed.

This commit is contained in:
Shine wOng
2019-08-05 21:37:59 +08:00
parent 4da20ee9c7
commit 2a8582ba72
4 changed files with 203 additions and 0 deletions

View File

@@ -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 <typename K, typename V>
class CBHeap: public Vector<entry<K, V>>, public PriorityQueue<K, V>{
protected:
//internal methods
void percolate_down(int pos);
void percolate_up(int pos);
int proper_parent(int pos);
public:
//constructor
CBHeap() = default;
CBHeap(entry<K, V>* src, int n);
int size() { return getSize(); }
bool empty(){ return size() == 0; }
void insert(entry<K, V> e);
void insert(K key, V value) { insert(entry<K, V>(key, value)); }
entry<K, V> getMax() { return _elem[0]; }
entry<K, V> delMax();
};
//internal methods
template <typename K, typename V>
int CBHeap<K, V>::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 <typename K, typename V>
void CBHeap<K, V>::percolate_down(int pos){
entry<K, V> 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 <typename K, typename V>
void CBHeap<K, V>::percolate_up(int pos){
entry<K, V> 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 <typename K, typename V>
CBHeap<K, V>::CBHeap(entry<K, V>* src, int n){
copyfrom(src, 0, n);
for (int ix = LASTINTERNAL; ix >= 0; --ix)
percolate_down(ix);
}
template <typename K, typename V>
void CBHeap<K, V>::insert(entry<K, V> e){
push_back(e);
percolate_up(getSize() - 1);
}
template <typename K, typename V>
entry<K, V> CBHeap<K, V>::delMax(){
entry<K, V> max = get(0);
_elem[0] = _elem[_size-- - 1];
percolate_down(0);
return max;
}
#endif

View File

@@ -0,0 +1,32 @@
#ifndef PRIORITYQUEUE_H_
#define PRIORITYQUEUE_H_
template <typename K, typename V>
class entry{
public:
K key;
V value;
//constructor
entry() = default;
entry(K k, V v) : key(k), value(v) {}
//overload operator
bool operator==(entry<K, V> const e) { return key == e.key; }
bool operator!=(entry<K, V> const e) { return key != e.key; }
bool operator>(entry<K, V> const e) { return key > e.key; }
bool operator<(entry<K, V> const e) { return key < e.key; }
bool operator>=(entry<K, V> const e) { return (key > e.key) || (key == e.key); }
};
template <typename K, typename V>
class PriorityQueue{
virtual int size() = 0;
virtual bool empty() = 0;
virtual entry<K, V> getMax() = 0;
virtual entry<K, V> delMax() = 0;
virtual void insert(K key, V value) = 0; //duplicate keys are allowed
virtual void insert(entry<K, V> e) = 0;
};
#endif

View File

@@ -0,0 +1,64 @@
#include "CompleteBinaryHeap.h"
#include <iostream>
#include <cassert>
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<int, int> src[10];
for (int ix = 0; ix != 10; ++ix)
src[ix] = entry<int, int>(keys[ix], 0);
CBHeap<int, int> 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<int, int> heap;
for(int ix = 0; ix != 10; ++ix){
assert(heap.size() == ix);
heap.insert(entry<int, int>(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<int, int> src[10];
for (int ix = 0; ix != 10; ++ix)
src[ix] = entry<int, int>(keys[ix], 0);
CBHeap<int, int> 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;
*/
}
}

14
thu_dsa/hash.md Normal file
View File

@@ -0,0 +1,14 @@
Conclusions on Hashing
======================
## 散列函数的设计
散列函数无非一个映射,其功能无非是将词条空间中的元素映射到散列表地址空间,其中前者远远大于后者,所以绝不可能是一个单射
好的散列函数
- 确定性:同一关键码总是被映射到同一地址
- 快速
- 满射:充分利用散列空间
- 均匀避免汇聚clustering。
散列函数
- 除余法
- MAD法
- 折叠法