快速排序、堆排序、归并排序

常见排序有7种:冒泡排序、希尔排序、插入排序、选择排序、快速排序、堆排序、归并排序。

此处讨论后三种时间复杂度为O(NlogN)的算法。

1,快速排序

一般情况下,快速排序迭代(或递归)次数为logN,每次恒进行N次比较;最差情况下迭代N次;

Partition部分:

int Partion(int a[], int low, int high)
{
    int i = low;
    int j = high;
    int val = a[low];
    while (i < j)
    {
        while (i < j && a[j] >= val) j--;
        if (i < j)    // 可能已经有序;
           a[i++] = a[j];
        while (i < j && a[i] <= val) i++;
        if (i < j) 
           a[j--] = a[i];
    }
    a[i] = val;
    return i;
}

QuickSort部分:(先调用Partition找到pivot对应的实际位置idx,然后分别对左右两部分递归)

void QuickSort(int a[], int low, int high)
{
    if (low < high)
    {
        int idx = Partition(a, low, high);
        QuickSort(a, low, idx-1);
        QuickSort(a, idx+1, high);
     }
}

附上快速排序视觉直观图:

《快速排序、堆排序、归并排序》

   

2,归并排序

归并排序和快速排序都是基于分治法(Divide and Conquer);需要注意的是归并排序空间复杂度O(N)。

合并两有序部分MergeArray:

void MergeArray(int a[], int low, int mid, int last, int tmp[])
{
    int i = low;
    int j = mid+1;
    int k = 0;
    while (i <= mid && j <= high)
    {
       if (a[i] <= a[j])
          a[k++] = a[i++];
       else
          a[k++] = a[j++];
    }
    while (i <= mid)
          a[k++] = a[i++];
    while (j <= high)
          a[k++] = a[j++];
    for (i = 0; i < k; i++)
         a[low+i] = tmp[i];
}    

MergeSort部分:

void Mergesort(int a[], int low, int high, int tmp[])
{
    if (low < high)
    {
        int mid = (low +high) / 2;
        MergeSort(a, low, mid, tmp);
        MergeSort(a, mid+1, high, tmp);
        MergeArray(a, low, mid, high, tmp);
    }
}

main函数调用:

int main()
{
    int n;
    int a[n];
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
         scanf("%d", &a[i]);
    int *p = (int *)malloc(n * sizeof(int));
    if (p == 0) return 1;
    MergeSort(a, 0, n-1, p);   //调用MergeSort排序
    free(p);
    return 0;
}    

继续附上归并排序视觉直观图:

《快速排序、堆排序、归并排序》

3,堆排序

作为一种数据结构,此处将堆设为一个类,含有的建堆、插入、删除作为方法封装于类中。

(int 类型的最小堆)

class MinHeap {
public: 
	MinHeap( int maxSize );//根据最大长度建堆
	MinHeap( int arr[], int n);          
	~MinHeap( ) { delete [] heap; }
	const MinHeap& operator=( const MinHeap &R );//重载赋值运算符
        int Insert(int x );
	int RemoveMin(int x );//移除关键码最小的元素,并赋给x
	bool IsEmpty( ) const { return CurrentSize == 0; }     
	int IsFull( ) const { return CurrentSize == MaxHeapSize; }
        void MakeEmpty( ) { CurrentSize = 0; }//使堆空
private: 
    enum { DefaultSize = 50 };//默认堆的大小
    int *heap;                 
    int CurrentSize;
    int MaxHeapSize;
    void FilterDown ( int i, int m ); //自上向下调整堆
    void FilterUp ( int i );          //自下向上调整堆
};
MinHeap::MinHeap ( int maxSize )
{
    MaxHeapSize = (DefaultSize < maxSize ) ? maxSize : DefaultSize;	     
    heap = new int[MaxHeapSize];  
    CurrentSize = 0;                              
}
MinHeap::MinHeap (int arr[], int n )
{ 
    MaxHeapSize = DefaultSize < n ? n : DefaultSize;
    heap = new int[MaxHeapSize]; 
    if(heap==NULL){cerr <<"fail" <<endl;exit(1);}
    for(int i =0; i< n; i++)
        heap[i] = arr[i];               //数组传送
    CurrentSize = n;       //当前堆大小
    int currentPos = (CurrentSize-2)/2;   //最后非叶
    while ( currentPos >= 0 ) 
    {       
        FilterDown ( currentPos, CurrentSize-1 );
	currentPos-- ;
    }
}
void MinHeap::FilterDown (int start,int EndOfHeap )
{
    int i = start,   j = 2*i+1;           // j 是 i 的左子女
    int temp = heap[i];
    while ( j <= EndOfHeap )
    {
	 if ( j < EndOfHeap && heap[j] > heap[j+1] )
	    j++;  //两子女中选小者
	 if ( temp<= heap[j] ) break;
	 else { heap[i] = heap[j];  i = j;   j = 2*j+1; }
    }
    heap[i] = temp;
}
int MinHeap::Insert (int x ) 
{
    if ( CurrentSize == MaxHeapSize )       //堆满
    { 
	cout << "堆已满" << endl;
        return 0; 
    }
    heap[CurrentSize] = x;        
    FilterUp (CurrentSize);          //向上调整为堆
    CurrentSize++;                       
    return 1;
}
void MinHeap::FilterUp (int start ) 
{
	int j = start;
        int i = (j-1) / 2;
        int temp = head[start];
        while (i < 0)
        {
           if (head[i] < temp) break;
           else
           {
              head[j] = head[i];
              j = i; 
              i = (i-1) / 2;
            }
         }
         head[j] = temp;
}
int MinHeap::RemoveMin(int x)
{
   if(CurrentSize == 0)
   {
     cout << "栈已空" << endl;
     return 1;
   }
   x = heap[0];
   heap[0] = heap[CurrentSize - 1];
   CurrentSize--;
   FilterDown(0, CurrentSize-1);
   return 0;
}

对数组排序即是调用MinHeap的含参构造函数MinHeap(int arr[], int n),过程为arr[]先对heap[]赋值,然后从第一个分支节点(CurrentSize-2)/2 到根节点进行FilterDown,时间复杂度O(NlogN);

Insert操作:将待插入元素x存入heap[CurrentSize], 从CurrentSize向上进行1次FilterUp,时间复杂度O(logN);

Remove操作:删除根元素(最小值),将heap[0]与heap[CurrentSize-1]对调,从根节点向下进行1次FilterDown, 时间复杂度O(logN);

文章内容由http://www.nowamagic.net/librarys/veda/detail/294 、 http://blog.csdn.net/morewindows/article/details/6709644 整理得到!

        

  

点赞