您的位置:首页 > 编程语言 > C语言/C++

[算法导论] 快速排序以及最大堆的C++实现

2013-02-16 14:49 656 查看

前言

重读了经典的<<算法导论>>时,我把书上的部分代码用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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: