几种常见排序算法

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、算法的时间复杂度和空间复杂度

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值