一、堆排序 : 原址排序 复杂度: nlg n

最大堆: A[parent(i)] > = A[i]

最小堆: A[parent(i)] < = A[i]

除了最底层外,其它层都是满状态。

判断节点是否为叶节点:  [n/2]+1,.....n 均为叶节点

//Max-heapify(A,i)   : A为一个 假定 left(i) right(i)的二叉树都是最大堆 。 但是A[i]可能小于孩子  。 时间复杂度为: o(h)
//build_max_heap(A,len) : 将一个数组转换为 最大堆(从底向上的建堆) , 时间复杂度为: o(n)
//heap_sort(A,len)      : 将 A 进行排序  复杂度 为 nlg(n)
void max_heapify(int *A , int i,int len)
{
        int r = RIGHT(i);
        int l = LEFT(i);
        int large = i;
        if (i <= len&&*(A + i-1) < *(A+r-1))
            large = r;
        if (i <= len && *(A+large-1)<*(A+l-1))
            large = l;
        if (large == i)
            return;
        else
            swap(A, large-1, i-1,len);
        if (i <= len && 2 * i < len/2+1)    // decide if  the left son node is leaf node 
            max_heapify(A, large, len);     // not leaf node , carry on the recursion 
        else
            return;                            // end the recursion
}

void build_max_heap(int *A, int len)
{
    for (int i = len / 2; i>0; i--)
        max_heapify(A,i,len);
}

void heap_sort(int *A, int len)
{
    build_max_heap(A,len);
    for (int i = len; i > 0; i--)
    {
        swap(A, i - 1, 0 ,len);
        max_heapify(A,1,i);
    }
}

二、快速排序   原址

最坏时间复杂度: n^2 ,但是是实际应用中最好的排序算法,期望时间复杂度:nlgn,而且隐藏的因子特别小。

 1 // partition();     将数组A[p,……,r] 分成 A[p,….,q-1]<=A[q]<=A[q+1,r],返回q的数组下标
 2 // quick_sort() :   递归调用,将分割好的数组继续分割
 3 int  PARTITION(int *A ,int p , int r ,int len)
 4 {
 5     if (p >= len || r >= len|| p<0||r<=0)
 6     {
 7         cout << "function PARTITION erro : the p or r is out range of the vector or array" << endl;
 8         return 0;
 9     }
10     int i = p - 1;
11     int x = 0;
12     for (int j = p; j < r; j++)
13     {
14         if (*(A+j)<*(A+r))
15         {
16             i = i + 1;
17             EXCHANGE(A,i,j,len);
18         }
19     }
20     EXCHANGE(A,r,i+1,len);
21     return i + 1;
22 }
23 void QUICK_SORT(int *A,int p,int r,int len)
24 {
25     if (p >= r)
26     {
27         cout << "function QUICK_SORT error : r must larger than p" << endl;
28         return;
29     }
30     if (p >= len || r >= len||p<0||r<=0)
31     {
32         cout << "function QUICK_SORT error : the p or r is out range of the vector or array" << endl;
33         return;
34     }
35     if (p == r)
36     {
37         cout << "end of calling of QUICK_SORT" << endl;
38         return;
39     }
40     int mid=PARTITION(A,p,r,len);
41     cout << "mid is :" << mid << "    p ="<<p<<"    r="<<r<<"    len="<<len<<endl;
42     QUICK_SORT(A,p,mid-1,len);
43     QUICK_SORT(A,mid+1,r,len);
44     output(A,len);
45 }

performance:

  worst situation: 

    T(n) = T(n-1) + k;  它的复杂度为 n^2 ,当数组已经是排好序的,那么他需要进行  n^2 次运算

  best situation: 

    T(n) = 2T(n/2)+k;  当两个子问题的规模都不大于n/2,这时候快速排序的性能最好  nlg n次运算

平衡的划分: 

  只要每次划分是一种常数比例的划分,都会产生深度为lgn的递归树

  例如: T(n) = T(n/10)+T(9n/10) + k;

quicksort using random function

RANDOMIZED-PARTITION(A, p, r):
    i = RANDOM(p, r )
    exchange A[r ] ↔ A[i ]
    return PARTITION(A, p, r )

三、线性时间排序

1、 决策树模型:

  每次比较判断可以影响下一次的比较,

定理:对于一个比较排序算法在最坏情况下,都需要做Ω(nlgn)次比较。

参考: http://www.cnblogs.com/Anker/archive/2013/01/25/2876397.html

2、计数排序 : 时间复杂度为n ,其实是max-min+1,需要额外开辟内存空间

前提条件: 所有的元素都必须在一个范围内,如:  min<a[i]<=max

int * count_sort(int *a ,int n){
    //initialize 
     int max=0xffffffff, min=0x7fffffff;
     for (int i = 0; i < n; i++){
         if (*(a + i)>max)
             max = *(a+i);
         if (*(a + i) < min)
             min = *(a + i);
     }
     const int len = max - min+1;
     int *c = new int[len];
     int *re = new int[n];
     memset(c,0,len*4);

     //count the number of every element in a[] then store in c[]
     for (int i = 0; i < n; i++){
         *(c + *(a+i) - min) += 1;
     }
     //sort based c[] 
     for (int i = 0,j=0; i < len; i++){
         int k = 0;
         while (k < *(c + i)){
             *(re + j) = min + i;
             j++;
             k++;
         }
     }
     delete []c;
     return re;
}

四:中位数和顺序统计量

1、期望为线性时间的选择算法: 最坏时间为n^2

RANDOMIZED_SELECT(A,p,r,i)
      if p==r
         then return A[p]
//通过partition函数产生q值,与快速排序的partition原理相同
      q = RANDOMIZED_PARTITION(A,p,r)
      k = q-p+1;
      if i==k
         then return A[q]
      else  if i<k
          then return RANDOMIZED_SELECT(A,p,q-1,i)
      else
          return RANDOMIZED_SELECT(A,p,q-1,i-k)

c++代码:

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

void swap(int* x, int* y)
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

inline int random(int x, int y)
{
    srand((unsigned)time(0));
    int ran_num = rand() % (y - x) + x;
    return ran_num;
}

int partition(int* arr, int p, int r)
{
    int x = arr[r];
    int i = p - 1;
    for(int j = p; j < r; j++)
    {
        if (arr[j] <= x)
        {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[r]);
    return ++i;
}

int randomizedpartition(int* arr, int p, int r)
{
    int i = random(p, r);
    swap(arr[r], arr[i]);
    return partition(arr, p, r);
}

int randomizedSelect(int* arr, int p, int r, int i)
{
    if(p == r)
    {
        return arr[p];
    }
    int q = randomizedpartition(arr, p, r);
    int k = q - p + 1;
    if(i == k)
    {
        return arr[q];
    }
    else if(i < k)
    {
        return randomizedSelect(arr, p, q - 1, i);
    }
    else
        return randomizedSelect(arr, q + 1, r, i - k);
}

int main()
{
    int arr[] = {1, 3, 5, 23, 64, 7, 23, 6, 34, 98, 100, 9};
    int i = randomizedSelect(arr, 0, 11, 4);
    cout << i << endl;
    return 0;
}
View Code

相关文章:

  • 2021-10-20
  • 2021-09-02
  • 2022-12-23
  • 2021-12-18
  • 2021-10-13
  • 2021-09-24
  • 2021-09-06
  • 2021-08-13
猜你喜欢
  • 2022-12-23
  • 2021-06-05
  • 2021-10-05
  • 2021-09-17
  • 2021-10-09
  • 2021-06-03
  • 2021-10-17
相关资源
相似解决方案