几种常见排序算法

1、冒泡排序

非递归实现

void bubbleSort(int *array,int len) {
    int tmp;
    bool flag;
    for (int i= len-1; i > 0; i--) {
        flag = false;
        for (int j = 0; j < i; j++) {
            if (array[j] > array[j+1]) {
                flag = true;
                tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;
            }
        }
        if (flag == false) {
            break;
        }
    }
}


递归实现

void bubbleSort(int *array,int len) {
    if (len > 1) {
        for (int i = 0; i < len-1;i++) {
            if (array[i] > array[i+1]) {
                int tmp = array[i];
                array[i] = array[i+1];
                array[i+1] = tmp;
            }
        }
        bubbleSort(array,len-1);
    }
}


-------思路:相邻元素对比大的往下挪,下次再从size-1数组中找次大的-------------

2、插入排序

非递归实现

void insSort(int *array,int len) {
    int index;
    int low;
    for (int i= 1; i < len; i++) {
        if (array[i] < array[i-1]) {
            index = array[i];
            low = i-1; 
            while (index < array[low] && low >= 0) {
                array[low+1] = array[low];
                low--;
            }
            if (low != i-1) {
                array[low+1] = index;
            }
        }
    }



递归实现

void insSort(int *array, int len,int pos) {
    if (pos > len-1) {
        return;
    }
    if (array[pos] < array[pos-1]) {
        int key = array[pos];
        int p = pos-1;
        while (array[p] >= key && p >= 0) {
            array[p+1] = array[p];  
            p--;
        }
        array[p+1] = key;
    }
    insSort(array,len,pos+1);
}

-------思路:每次从已经排序好的k个数组中添加第k+1个数据,从k数组中以该数值为第k+1数据为标杆找到该的数据的正确位置,比之大的数据往后挪一个位置。-------

3、堆排序

/*堆排序(大顶堆) 2011.9.14*/ 

#include <iostream>
#include<algorithm>
using namespace std;

void HeapAdjust(int *a,int i,int size) //调整堆
{
int lchild=2*i; //i的左孩子节点序号
int rchild=2*i+1; //i的右孩子节点序号
int max=i; //临时变量
if(i<=size/2) //如果i是叶节点就不用进行调整
{
if(lchild<=size&&a[lchild]>a[max])
{
max=lchild;
}
if(rchild<=size&&a[rchild]>a[max])
{
max=rchild;
}
if(max!=i)
{
swap(a[i],a[max]);
HeapAdjust(a,max,size); //避免调整之后以max为父节点的子树不是堆
}
}
}

void BuildHeap(int *a,int size) //建立堆
{
int i;
for(i=size/2;i>=1;i--) //非叶节点最大序号值为size/2
{
HeapAdjust(a,i,size);
}
}

void HeapSort(int *a,int size) //堆排序
{
int i;
BuildHeap(a,size);
for(i=size;i>=1;i--)
{
//cout<<a[1]<<" ";
swap(a[1],a[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
//BuildHeap(a,i-1); //将余下元素重新建立为大顶堆
HeapAdjust(a,1,i-1); //重新调整堆顶节点成为大顶堆
}
}

int main(int argc, char *argv[])
{
//int a[]={0,16,20,3,11,17,8};
int a[100];
int size;
while(scanf("%d",&size)==1&&size>0)
{
int i;
for(i=1;i<=size;i++)
cin>>a[i];
HeapSort(a,size);
for(i=1;i<=size;i++)
cout<<a[i]<<"";
cout<<endl;
}
return 0;
}
-----------------------------求最大的k个数-----------------
#include <iostream>
#include<algorithm>
using namespace std;


void HeapAdjust(int *a,int i,int size)  //调整堆 
{
    int lchild=2*i;       //i的左孩子节点序号 
    int rchild=2*i+1;     //i的右孩子节点序号 
    int min=i;            //临时变量 
    if(i<=size/2)          //如果i是叶节点就不用进行调整 
    {
        if(lchild<=size&&a[lchild]<a[min])
        {
            min=lchild;
        }    
        if(rchild<=size&&a[rchild]<a[min])
        {
            min=rchild;
        }
        if(min!=i)
        {
            swap(a[i],a[min]);
            HeapAdjust(a,min,size);    //避免调整之后以min为父节点的子树不是堆 
        }
    }        
}
 
 
void BuildHeap(int *a,int size)    //建立堆 
{
    int i;
    for(i=size/2;i>=1;i--)    //非叶节点最大序号值为size/2 
    {
        HeapAdjust(a,i,size);    
    }    
} 
void HeapSort(int *a,int size,int nselect)    //堆排序 
{
    int i;
    BuildHeap(a,nselect);
        for(i = nselect+1;i <= size;i++) {
                if (a[1] < a[i]) {
                        swap(a[i],a[1]);
                        HeapAdjust(a,1,nselect);
                }
        }
}
 
 
int main(int argc, char *argv[])
{
     //int a[]={0,16,20,3,11,17,8};
    int a[100];
        int nselect = atoi(argv[1]);
    int size;
    while(scanf("%d",&size)==1&&size>0)
    {
        int i;
        for(i=1;i<=size;i++)
            cin>>a[i];
        HeapSort(a,size,nselect);
        for(i=1;i<=nselec;i++)
            cout<<a[i]<<" ";
        cout<<endl;
    }
    return 0;
}
-----------思路:先用k个数组成最小堆,然后判断后面的是否小于第一个如果小于则忽略,否则替换第一个然后调整最小堆---------
 
 
 
 
4、归并排序
  
  
  
  
  1. //将有二个有序数列a[first...mid]和a[mid...last]合并。  
  2. void mergearray(int a[], int first, int mid, int last, int temp[])  
  3. {  
  4.     int i = first, j = mid + 1;  
  5.     int m = mid,   n = last;  
  6.     int k = 0;  
  7.       
  8.     while (i <= m && j <= n)  
  9.     {  
  10.         if (a[i] <= a[j])  
  11.             temp[k++] = a[i++];  
  12.         else  
  13.             temp[k++] = a[j++];  
  14.     }  
  15.       
  16.     while (i <= m)  
  17.         temp[k++] = a[i++];  
  18.       
  19.     while (j <= n)  
  20.         temp[k++] = a[j++];  
  21.       
  22.     for (i = 0; i < k; i++)  
  23.         a[first + i] = temp[i];  
  24. }  
  25. void mergesort(int a[], int first, int last, int temp[])  
  26. {  
  27.     if (first < last)  
  28.     {  
  29.         int mid = (first + last) / 2;  
  30.         mergesort(a, first, mid, temp);    //左边有序  
  31.         mergesort(a, mid + 1, last, temp); //右边有序  
  32.         mergearray(a, first, mid, last, temp); //再将二个有序数列合并  
  33.     }  
  34. }  
  35.   
  36. bool MergeSort(int a[], int n)  
  37. {  
  38.     int *p = new int[n];  
  39.     if (p == NULL)  
  40.         return false;  
  41.     mergesort(a, 0, n - 1, p);  
  42.     delete[] p;  
  43.     return true;  
----------思路:分而治之,先分再和,递归分,和时将两个排序好的数组再借用临时数组重组,之后再重新复制给原数组---------
5、快速排序
void quickSort(int *array, int l, int r) {     if (l < r) {         int i = l, j = r, index = array[l];         while (i < j) {             while (array[j] >= index) {                 j--;             }             if (i < j) {                 array[i++] = array[j];             }             while (array[i] < index) {                 i++;                 }             if (i < j) {                 array[j--] = array[i];             }         }         array[i] = index;         quickSort(array,l,i-1);         quickSort(array,i+1,r);     } }
----思路:每次都以数组中的某一个值(可以随机)作为标杆,依次从左至右遍历将比它小的排在左边,大的排右边,可以得到标杆应该放的位置再递归----
6、选择排序
void selSort(int *array,int len) {     int index;     int tmp;     for (int i= len-1; i > 0; i--) {         index = i;         for (int j = 0; j < i; j++) {             if (array[j] > array[index]) {                 index = j;             }         }         if (i != index) {             tmp = array[i];             array[i] = array[index];             array[index] = tmp;         }     } }
-----思路:和冒泡排序有点类似,每次从数组中找最大的数据排在最后,但是不需要像冒泡排序挪位置------


===========================各种排序算法的比较============================

1.稳定性比较

插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的

选择排序、希尔排序、快速排序、堆排序是不稳定的

2.时间复杂性比较

     平均情况  最好情况 最坏情况
归并排序 O(nlogn)  O(nlogn) O(nlogn)
基数排序 O(n) O(n) O(n)
快速排序 O(nlogn) O(nlogn) O(n2)
希尔排序 O(n1.5) O(n) O(n1.5)
插入排序 O(n2) O(n) O(n2)

选择排序

O(n2) O(n2) O(n2)

 

 

 

 

 

 

3.辅助空间的比较

线形排序、二路归并排序的辅助空间为O(n),其它排序的辅助空间为O(1);

4.其它比较

插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。

反而在这种情况下,快速排序反而慢了。

当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。

若待排序的记录的关键字在一个明显有限范围内时,且空间允许是用桶排序。

当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。

当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下。

宜用归并排序。

当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。

*************************************************************************************

相关知识介绍(所有定义只为帮助读者理解相关概念,并非严格定义): 1、稳定排序和非稳定排序

简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就 说这种排序方法是稳定的。反之,就是非稳定的。 比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5, 则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。假如变成a1,a4, a2,a3,a5就不是稳定的了。

2、内排序和外排序

在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序; 在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。

3、算法的时间复杂度和空间复杂度

所谓算法的时间复杂度,是指执行算法所需要的计算工作量。 一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。


你可能感兴趣的:(冒泡排序,递归,插入排序,排序算法)