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

来源:互联网 发布:云服务器搭建sql serv 编辑:程序博客网 时间:2024/05/01 19:29

常见排序有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 );//移除关键码最小的元素,并赋给xbool 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 整理得到!

        


  




0 0
原创粉丝点击