前言
重读了经典的<<算法导论>>时,我把书上的部分代码用C++实现,然后与自己之前写的代码对比一下,不禁为<<导论>>中算法实现的精简和优美所折服。今天把代码堆出来,以备不时之需。
快速排序
/*
* 2013-02-02 22:20 mingspy 算法导论
*/
#pragma once
#include <iostream>
#include <time.h>
#include <stdlib.h>
using std::cout;
using std::endl;
namespace alg_intro{
/**************************************************************************
*快速排序 - 递归方法
*对数组A[r, q]进行快速排序
*QuickSort(A, r, q)
*{
* if (r >= q) return;
* t <- Patition(A, r, q); //对数据分区
* QuickSort(A, r, t - 1); //排序左半边
* QuickSort(A, t + 1, q); //排序右半边
*}
*
*int Patition(A, r, q)
*{
* i = r - 1;
* FOR j <- r to q - 1 { //选择最后一个作为中值
* IF A[j] < A[q] THEN
* i <- i + 1
* A[i]<->A[j] //交换
* }
*
* i <- i + 1
* A[i]<->A[q]
* return i;
*}
*/
long recall_times = 0;
template<class T>
void InsertSort(T * data,long r, long q)
{
for(int i = r+1; i <= q ; i++){
T t = data[i];
int j = i;
for(; j > 0 && t < data[j - 1]; j --)
data[j] = data[j - 1];
data[j] = t;
}
}
template<typename T>
long Patition(T * data, long r, long q)
{
long i = r - 1;
for(long j = r; j < q ; j++){
if (data[j] < data[q]){
i++;
Swap(data, i, j);
}
}
i++;
Swap(data, i, q);
return i;
}
template<typename T>
long RandomPatition(T *data, long r, long q)
{
long len = q - r + 1;
long p = r + (Random() % len);
Swap(data, q, p);
return Patition(data, r, q);
}
template<typename T>
void QuickSort(T * data, long r, long q)
{
//recall_times ++;
if (r >= q) return;
if(q - r < 16){
InsertSort(data, r, q);
return;
}
long t = RandomPatition(data, r, q);
QuickSort(data, r, t - 1);
QuickSort(data, t + 1, q);
}
template<typename T>
void Print(T * data, long len)
{
for (long i = 0; i < len; i ++ )
cout<<data[i]<<" ";
cout << endl;
}
}
int main(void)
{
int len = 20000000;
int * data = new int[len];
for(int i = 0; i < len; i ++){
data[i] = alg_intro::Random();
}
//alg_intro::Print(data, 100);
time_t start = time(0);
alg_intro::QuickSort(data, 0, len - 1);
time_t end = time(0);
cout << "sort "<<len <<" data used " << (end - start)<<"s"
<<" call quick "<<alg_intro::recall_times<<endl;
//alg_intro::Print(data, 100);
delete []data;
puts("Press Enter to quit!");
getchar();
return 0;
}
最大堆及堆排序
/*
* 2013-02-04 23:15 mingspy 算法导论
*/
#pragma once
#include <iostream>
#include <assert.h>
#include "alg_utilies.h"
namespace alg_intro{
/*
* 获取堆数组左孩子节点下标, 下标0处也存放数据
*/
inline int Left(int i) { return (i<<2) + 1;}
/*
* 获取堆数组右孩子节点下标, 下标0处也存放数据
*/
inline int Right(int i) {return (i<<2) + 2;}
/*
* 获取堆数组父节点下标, 下标0处也存放数据
*/
inline int Parent(int i) { return (i+1)>>2;}
/*
*最大堆,A[Parent(i)]>=A[i]
*/
template<typename T>
class MaxHeap{
public:
MaxHeap(int cap):size(0), capability(cap){
A = new T[cap];
}
MaxHeap(const T * A, int len):size(len), capability(len){
A = new T[len];
memcpy(A, arr, len * sizeof(T));
}
~MaxHeap(){
delete [] A;
A = 0;
}
/*
* Max-Heapify(A, i) 保持i节点最大堆的性质, 注意书上A[1...n]
* l <- LEFT(i)
* r <- RIGHT(i)
* if l<= heap-size[A] and A[l] > A[i]
* then largest <- l
* else largest <- i
* if r <= heapsize(A) and A[r] > A[largest]
* then largest <- r
* if largest != i
* then exchange A[i]<->A[largest]
* Max-Heapify(A, largest)
*/
void Heapify(int i){
int l = Left(i);
int r = Right(i);
int largest = i;
if ( l < size && A[l] > A[largest]){
largest = l;
}
if ( r < size && A[r] > A[largest]){
largest = r;
}
if ( i != largest){
Swap(A, i, largest);
Heapify(largest);
}
}
void HeapifyUp(int i){
int parent;
while (i > 0 && A[(parent=Parent(i))] < A[i]){
Swap(A, i, parent);
i = parent;
}
}
/*
* Build-Max-Heap(A) 构建最大堆 A[1...n]
* heap-size[A] <- length[A]
* for i <- foot[length[A]/2] downto 1
* do Max-Heapify(A,i);
*/
void Build(){
if ( size == 0) return;
for (int i = (size - 1) / 2; i >= 0; i--){
Heapify(i);
}
}
/*
*HeapSort(A) 堆排序 A[1...n]
* Build-Max-Heap(A)
* for i <- length[A] down to 2 //从最后一个元素开始
* do exchange A[1] <->A[i] //把最大元素交换到i
* heap-size[A] <- heap-size[A] - 1 //
* Max-Heapify(A, i) //重建堆
*/
void Sort()
{
if(size == 0) return;
size_t tmpSize = size;
Build();
for (int i = --size; i > 0; i--)
{
Swap(A, i, 0);
--size;
Heapify(0);
}
size = tmpSize;
}
bool Empty() { return size == 0;}
/*
* Heap-Maximum(A) 返回最大值 A[1...n]
* return A[1]
*/
T GetMax(){
assert (size > 0); //or不做判断,由外部进行Empty()判断
return A[0];
}
/*
*Heap-Extract-Max(A) 删除最大值 A[1...n]
* if heap-size[A] < 1
* then error "heap underflow"
* max <- A[1]
* A[1] <-A[heap-size[A]]
* heap-size[A] <- heap-size[A] - 1
* Max-Heapify(A, 1)
* return max;
*/
T ExtractMax(){
assert (size > 0);
T max = A[0];
A[0] = A[--size];
Heapify(0);
return max;
}
/*
*Heap-Increase-Key(A, i, key) 变化A[i]处的值为更大的值
* if key < A[i]
* then error "new key is smaller"
* A[i] <- Key
* while i > 1 and A[Parent(i)] < A[i]
* do exchange A[i] <-> A[Parent(i)]
* i <- Parent(i)
*/
void IncreaseKey(int i, T key){
assert(i>=0 && i < size);
assert(A[i] < key);
A[i] = key;
HeapifyUp(i);
}
/*
*Max-Heap-Insert(A,key)
* heap-size[A] <- heap-size[A] + 1
* A[heap-size[A]] <- -INFINITY
* Heap-Increase-Key(A, heap-size[A], key)
*/
void Insert(T key){
assert(size + 1 < capability);
A[size] = key;
HeapifyUp(size);
size ++;
}
private:
size_t size; // 当前大小
size_t capability; // 最大大小
T * A;
};
}
void Test_MaxHeap()
{
alg_intro::MaxHeap<int> heap(10);
heap.Insert(0);
heap.Insert(9);
heap.Insert(5);
heap.IncreaseKey(1, 10);
heap.Insert(20);
std::cout<<"20 20 10 9 5 =>if next line is same as these number, correct!"<<std::endl;
std::cout<<heap.GetMax();
while(!heap.Empty()){
std::cout<<" "<<heap.ExtractMax();
}
std::cout<<std::endl;
}
最小堆
template<typename T>
class MinHeap{
public:
MinHeap(int cap = 10):_size(0), _capability(cap){
A = new T[cap];
}
MinHeap(const T * A, int len):_size(len), _capability(len){
A = new T[len];
memcpy(A, arr, len * sizeof(T));
}
MinHeap(const MinHeap & r):_size(r._size), _capability(r._capability){
A = new T[r._capability];
memcpy(A, r.A, r._capability * sizeof(T));
}
~MinHeap(){
delete [] A;
A = 0;
}
/*
* Max-Heapify(A, i) A[1...n]
* l <- LEFT(i)
* r <- RIGHT(i)
* if l<= heap-size[A] and A[l] > A[i]
* then largest <- l
* else largest <- i
* if r <= heapsize(A) and A[r] > A[largest]
* then largest <- r
* if largest != i
* then exchange A[i]<->A[largest]
* Max-Heapify(A, largest)
*/
void Heapify(int i){
int l = Left(i);
int r = Right(i);
int smallest = i;
if ( l < _size && A[l] < A[smallest]){
smallest = l;
}
if ( r < _size && A[r] < A[smallest]){
smallest = r;
}
if ( i != smallest){
Swap(i, smallest);
Heapify(smallest);
}
}
void HeapifyUp(int i){
int parent;
while (i > 0 && A[i] < A[(parent=Parent(i))]){
Swap(i, parent);
i = parent;
}
}
/*
* Build-Max-Heap(A) A[1...n]
* heap-size[A] <- length[A]
* for i <- foot[length[A]/2] downto 1
* do Max-Heapify(A,i);
*/
void Build(){
if ( _size == 0) return;
for (int i = (_size - 1) / 2; i >= 0; i--){
Heapify(i);
}
}
/*
*HeapSort(A) A[1...n]
* Build-Max-Heap(A)
* for i <- length[A] down to 2 //
* do exchange A[1] <->A[i] //
* heap-size[A] <- heap-size[A] - 1 //
* Max-Heapify(A, i) //
*/
void Sort()
{
if(_size == 0) return;
size_t tmpSize = _size;
Build();
for (int i = --_size; i > 0; i--)
{
Swap(i, 0);
--_size;
Heapify(0);
}
_size = tmpSize;
// reverse
int mid = _size / 2;
for(int i = 0; i < mid ; i++){
Swap(i, _size - 1 - i);
}
}
bool Empty() { return _size == 0;}
/*
* Heap-Maximum(A)
* return A[1]
*/
T & GetMin(){
assert (_size > 0); //
return A[0];
}
T & Get(int idx){
assert (_size > 0); //
return A[idx];
}
/*
*Heap-Extract-Max(A) A[1...n]
* if heap-size[A] < 1
* then error "heap underflow"
* max <- A[1]
* A[1] <-A[heap-size[A]]
* heap-size[A] <- heap-size[A] - 1
* Max-Heapify(A, 1)
* return max;
*/
T RemoveMin(){
assert (_size > 0);
T min = A[0];
A[0] = A[--_size];
Heapify(0);
return min;
}
/*
*Heap-Increase-Key(A, i, key)
* if key < A[i]
* then error "new key is smaller"
* A[i] <- Key
* while i > 1 and A[Parent(i)] < A[i]
* do exchange A[i] <-> A[Parent(i)]
* i <- Parent(i)
*/
void IncreaseKey(int i, const T & key){
assert(i>=0 && i < _size);
A[i] = key;
HeapifyUp(i);
}
/*
*Max-Heap-Insert(A,key)
* heap-size[A] <- heap-size[A] + 1
* A[heap-size[A]] <- -INFINITY
* Heap-Increase-Key(A, heap-size[A], key)
*/
void Insert(const T & key){
assert(_size < _capability);
A[_size] = key;
HeapifyUp(_size);
_size ++;
}
size_t size() const{
return _size;
}
/*
* add key only if key is letter than
* A[_size] when the heap is full.
* useful when do NPath.
*/
void ConditionAdd(const T & key){
if(_size < _capability){
A[_size] = key;
HeapifyUp(_size);
_size ++;
}else if(key < A[_size - 1]){
A[_size - 1] = key;
HeapifyUp(_size - 1);
}
}
private:
inline void Swap(int i, int j)
{
T t = A[i];
A[i] = A[j];
A[j] = t;
}
size_t _size; //
size_t _capability; //
T * A;
};