排序算法总结

1 冒泡排序

排序思想:每次选出最大的放到序列末尾,序列每次去除最后的元素,直到剩下最后一个元素排序结束。

特点:在寻找本轮最大元素时可以设置一个标志位,如果一轮下来标志位没变说明所有元素都以有序。平均时间复杂度为O(n^2)。

2 插入排序

排序思想:在对第i个元素进行添加时,前面i-1个元素已经排序结束,将第i个元素插入到前面i-1个元素的适当位置即可。

特点:当元素基本有序时只需要做比较和少量的换序即可。平均时间复杂度为O(n^2)。

递归实现的代码:

template<class T>
void insert_sort(T A[],int n){
  if(n<1)
    return;
  insert_sort(A,n-1); 

  int a = A[n];
  int k = n-1;
  while(k>=0 &&A[k]>a){
    A[k+1] = A[k];
    k = k-1;
  }
  A[k+1] = a; // k+1恰好是空出那个元素
}

3 归并排序

排序思想:长度为N的序列可以分为两个长度为N/2的序列,如果两个长度为N/2的序列已经有序,那么使用合并算法【见附录】合并即可,这样问题的规模就减小为两个长度为N/2序列的排序问题,递归即可。

特点:平均时间复杂度为O(n*logn)。

4 选择排序

排序思想:每次从待排序数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

特点: 选择排序是不稳定的排序方法,平均时间复杂度为O(n^2)。

5 堆排序

排序思想:使用待排序数据建立一个堆,堆是这样一种数据结构:所有父节点数据均大于(或小于)子节点数据。这样每次取出根节点即可获得有序序列。

特点:堆排序没有使用额外的存储空间!!平均时间复杂度是O(n^2)。

附录:

合并算法:

template <class Type>
void merge(Type A[],int p,int q,int r)
{
    Type *bp = new Type[r-p+1];  //这种方式的缺点就是需要开辟较大的内存空间!
    int i=p,j=1+q,k=0;
   
   
    while (i<=q && j<=r)
        if(A[i] <= A[j])
            bp[k++] = A[i++];
        else
            bp[k++] = A[j++];
       
        if(i==q+1)  //这里必须注意写法,不能使用< 判断,因为最后停留的位置不能确定,但是这个条件能确定
            for(;j<=r;j++)
                bp[k++] = A[j];
            else
                for (;i<=q;i++)
                    bp[k++] = A[i];
               
                k=0;
                for (i=p;i<=r;i++)
                    A[i] = bp[k++];
               
                delete bp;
}

堆操作:

1 元素上移:

void shift_up(int H[],int i){
    int value = H[i];
    int pos = i;
    while(i/2 >= 1 && value > H[i/2]){
        pos = i/2;
        H[i] = H[i/2];
        i = i/2;
    }
    H[pos] = value;
}

2 元素下移:

void shift_down(int H[],int n,int i){
  int value = H[i];
  bool flag = false;
  int pos = i;
  while(i*2 <= n){
    int j;
    if(i*2 == n)  //一定要判断数组是否越界
      j = i*2;
    else
      j = H[2*i] >= H[2*i+1] ? 2*i :2*i + 1;
    if(value<H[j]){
      pos = j;
      H[i] = H[j];
      i = j;
    }else{ //停止查找
      break;
    }
  }
  H[pos] = value;  //最终的位置!
}

3 元素插入:

void insert(int H[],int &n,int value){  //注意这里n要使用引用变量
    n = n+1;
    H[n] = value;
    shift_up(H,n);
}

4 元素删除

void delete_i(int H[],int &n,int i){
    value = H[i];
    last = H[n];
    n = n - 1;
    H[i] = last;
    if(last > value)
        shift_up(H,i);
    else
        shift_down(H,n,i);   
}

5 删除堆顶元素

int delete_max(int H[],int &n){
    int max = H[1];
    delete_i(H[],n,1);
    return max;
}

堆建立:

void make_heap(int A[],int H[],int n){
    int num = 0;
    for(i=0;i<n;i++){
        insert(H,num,A[i]);
    }
}

void make_heap_self(int H[],int n){   
    A[n] = A[0];  //这个比较特殊。。
    for(i = n/2;i>=1;i--){
        shift_down(H,n,i);
    }
}

堆排序:

void heap_sort(int A[],int n){
  int i;
  make_heap_self(A,n);
  for(i=n;i>1;i--){
    swap(A,i,1);
    shift_down(A,i-1,1);
  }
}

原文地址:https://www.cnblogs.com/guojidong/p/2825388.html