排序

定义
快速排序是对冒泡排序的一种改进。

基本思想
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

算法思想
假设序列中有 n 个数,将这 n 个数放到数组 a 中。
算法:

设置两个变量 i、j,排序开始的时候:low=0,high=n–1。

(1)以数组第一个元素为关键数据,赋给变量 key,即 key=a[0]。
(2)从high 开始向前搜索,即由后开始向前搜索(high–),找到第一个小于 key 的值 a[high],将 a[high] 和 a[low] 互换。
(3)然后再从 low 开始向后搜索,即由前开始向后搜索(++low),找到第一个大于 key 的 a[low],将 a[low] 和 a[high] 互换。
(4)重复第 2、3 步,直到 low=high。此时就能确保序列中所有元素都与 key 比较过了,且 key 的左边全部是比 key 小的,key 的右边全部是比 key 大的。

第一轮比较后序列就以 key 为中心分成了左右两部分,然后分别对左右两部分分别递归执行上面几个步骤,直到排序结束。

a={50,10,90,30,70,40,80,60,20};
在这里插入图片描述
代码:

#include<stdio.h>
int Split(int *a,int low,int high)  /*将比key大的放一边,比key小的放一边*/
{
    int key,temp;
    key=a[low];
    while(low<high)
    {
        while(low<high&&a[high]>=key)
            high--;
        {
            temp=a[low];
            a[low]=a[high];
            a[high]=temp;
        }
        while(low<high&&a[low]<=key)
            low++;
        {
            temp=a[low];
            a[low]=a[high];
            a[high]=temp;
        }
    }
    return low;
}
void Quicksort(int *a,int low,int high)
{
    int p;
    if(low<high)
    {
        p=Split(a,low,high);
        Quicksort(a,low,p-1);
        Quicksort(a,p+1,high);
    }
}
void main()
{
    int n,a[1000],i;
    scanf("%d",&n);
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    Quicksort(a,0,n-1);
    printf("最终排序结果:\n");
    for(i=0;i<n;i++)
        printf("%d ",a[i]);
}

快速排序优化
1,优化选取key
三数取中法。即取三个关键字先进行排序,将中间数作为key,一般是取左端,右端和中间三个数,也可以随机选取。
在Split函数代码的第3行与第4行之间增加这样一段代码。

int m=low+(high-low)/2  /*计算数组中间元素的下标*/
if(a[low]>a[high])
{
    temp=a[low];
    a[low]=a[high];
    a[high]=temp;
}
if(a[m]>a[high])
  {
    temp=a[m];
    a[m]=a[high];
    a[high]=temp;
}  
if(a[m]<a[low])
  {
    temp=a[m];
    a[m]=a[low];
    a[low]=temp;
}  

2,优化不必要的交换
将a[0]用作哨兵或临时变量。将key备份到a[0],采用替换而不是交换的方式。

int Split(int *a,int low,int high) /*将比key大的放一边,比key小的放一边*/
{
    int key,temp;
    int m=low+(high-low)/2;
    if(a[low]>a[high])
    {
        temp=a[low];
        a[low]=a[high];
        a[high]=temp;
    }
    if(a[m]>a[high])
    {
        temp=a[m];
        a[m]=a[high];
        a[high]=temp;
    }
    if(a[m]>a[low])
    {
        temp=a[m];
        a[m]=a[low];
        a[low]=temp;
    }

    key=a[low];
    a[0]=key;/*将key备份到a[0]*/
    while(low<high)
    {
        while(low<high&&a[high]>=key)
            high--;
        a[low]=a[high];/*采用替换而不是交换的方式进行操作*/
        while(low<high&&a[low]<=key)
            low++;
        a[high]=a[low];/*采用替换而不是交换的方式进行操作*/
    }
    a[low]=a[0];/*将key数值替换回a[low]*/
    return low;
}

3,优化小数组时的排序方案
当high-low小于等于数组长度阀值时用直接插入法;
当high-low大于数组长度阀值时用快速排序。

4,优化递归操作

void Quicksort(int *a,int low,int high)
{
    int p;
    while(low<high)
    {
        p=Split(a,low,high);
        Quicksort(a,low,p-1);
        low=p+1; /*尾递归*/
    }
}
#include<stdio.h>
void quicksort(int a[],int low,int high)
{
    int i,j,key;
    i=low;
    j=high;
    key=a[i];
    if(i>=j)
        return ;
    while(i<j)
    {
        while(i<j&&a[j]>=key)
            j--;
        a[i]=a[j];
        while(i<j&&a[i]<=key)
            i++;
        a[j]=a[i];
    }
    a[i]=key;
    quicksort(a,low,i-1);
    quicksort(a,i+1,high);
}
void main()
{
    int a[10000];
    int i,n;
    scanf("%d",&n);
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    quicksort(a,0,n-1);
    for(i=0;i<n;i++)
        printf("%d ",a[i]);

}

选择排序:

void choosesort(int a[],int n)
{
    int i,j,min,tmp;
    for(i=0;i<n-1;i++)
    {
        min=i;
        for(j=i+1;j<n;j++)
          {
              if(a[j]<a[min])
                min=j;
          }
        if(i!=min)
        {
            tmp=a[i];
            a[i]=a[min];
            a[min]=tmp;
        }
    }
}

直接插入排序:

void insertsort(int a[],int n)
{
    int i,j,key;
    for(i=1;i<n;i++)
    {
        key=a[i];
    for(j=i-1;j>=0;j--)
     {
        if(a[j]>key)
           a[j+1]=a[j];
        else
            break;
     }
     a[j+1]=key;
    }
}

希尔排序:

void shellsort(int a[],int n)
{
    int i,j,key,step;
    for(step=n/2; step>=1; step=step/2)
    {
        for(i=step; i<n; i++)
        {
            key=a[i];
            for(j=i-step; j>=0; j=j-step)
            {
                if(a[j]>key)
                    a[j+step]=a[j];
                else
                    break;
            }
            a[j+step]=key;
        }
    }
}

归并排序:

b[10000];
void mergesort(int a[],int low,int high)
{
    int i,j,k,mid;
    if(low==high)
        return;
    i=low;
    k=i;
    mid=(low+high)/2;
    j=mid+1;
    mergesort(a,low,mid);
    mergesort(a,mid+1,high);
    while(i<=mid&&j<=high)
    {
        if(a[i]<=a[j])
        {
            b[k]=a[i];
            i++;
        }
        else
        {
            b[k]=a[j];
            j++;
        }
        k++;
    }
    while(i<=mid)
    {
        b[k]=a[i];
        i++;
        k++;
    }
    while(j<=high)
    {
        b[k]=a[j];
        j++;
        k++;
    }
    for(i=low;i<=high;i++)
        a[i]=b[i];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值