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

前言

重读了经典的<<算法导论>>时,我把书上的部分代码用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;  
    };  



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值