经典排序算法总结

本文章对之前了解过的排序算法进行简单的总结与解释:

以该数组为例:a[5]={41,23,57,18,47};

冒泡排序:

思想:冒泡排序是前后两项对比,因此要对比数据量为N-1轮,每一轮中,前后两数进行对比,过程如下:

从第一项开始,前后两项进行对比,若前项大于后项,则交换位置,如上例中,41大于23,交换位置为a[5]={23,41,57,18,47};接着41与57对比,不大于,不变,57又和18对比,大于18,交换位置得a[5]={23,41,18,57,47};接着57与47对比,大于47,交换位置得a[5]={23,41,18,47,57};最大数置于最末尾,结束第一轮。第二轮依旧从第一项开始,但由于最大数已经置于末尾,因此下次对比就比上一轮少对比一次(57不参与对比),23与41对比,不大于,不变,41与18对比,大于,交换位置得a[5]={23,18,41,47,57};接着继续以上步骤,对比结束后就成功得到了一组有序数据。

代码如下:

#include<stdio.h>
int main(void)
{
    int a[5]={23,41,18,47,57};
    int i,j,t;
    for(i=0;i<4;i++)//对比轮数
    {    
        for(j=0;j<4-i;j++)//对比项数
        {
            if(a[j]>a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
         }
    }
}

选择排序:

思想:遍历数组,选择最小的值放到头部(头部值与最小值调换位置),然后头部的下一项作为新的头部继续以上过程,对比N-1轮。

例如:a[5]={41,23,57,18,47}中41与23对比,23小于41,交换位置得a[5]={23,41,57,18,47}然后 a[0](也就是23)继续与下一项57对比,不大于57,不换,继续下一项,18小于23,变为:a[5]={18,41,57,23,47},继续对比,18不大于47,不变,第一轮结束,接着第二轮忽略a[0](最小值不用对比),以a[1]为头重复以上步骤,直到最后一项为头,结束对比(最后一项必然最大,所以不用比,从而只需对比N-1次)

代码如下:

#include<stdio.h>
int main(void)
{
    int a[5]={41,23,57,18,47};
    int i,j,t;
    for(i=0;i<4;i++)
    {
        for(j=i;j<5;j++)
        {
            if(a[i]>a[j])
            {
            t=a[i];
            a[i]=a[j];
            a[j]=t;
             }
        }
    }
}

插入排序:

思想:假定有一组有序数据,然后在一个新数据出现后,把新数据放入有序数据的合适位置中。那么在排一组数据时,我们可以先拿出两个数据41,23(无论如何均是有序的),然后把第三个数据57和两个数据对比,将其放到41前面得到57,41,23,然后再放入数据18,其比23小,则放到23后面,按该原理就能排好序。

在插入排序中加入递归思想,就能更好的编写代码,在递归中,递归调用的趋势是数组长度的减短,停止递归条件为数组中只有两个数据,每次函数结束后,要完成的功能是把上层递归中多的数放到合适的位置。

按以上思想编写代码为:

#include<stdio.h>
int fun(int *a,int len)
{
    if(len<2)//停止递归条件
    {
       return 0;
    }
    fun(a,len-1);//递归趋势
    int i=len-1;
    int t=a[len+1];
    for(;i>=0;i++)//只要新插入的数不大于其中某个数,就让所有的数向后移一位
    {
        if(t>a[i])//大于某个数(代表在两个数间,或者在数组末尾,证明是合适位置)退出循环
        {
            break;
        }
        a[i+1]=a[i];
    }
        a[i+1]=t;//插入数据
}
int main(void)
{
    int a[5]={41,23,57,18,47};
    int len=sizeof(a)/sizeof(int);
    fun(a,len);
    for(i=0;i<len;i++)
     {
          printf("%d ",a[i]);
     }

}

注意:len的长度要算对,不然容易出现栈溢出。

快速排序:

思想:选择一个数作为标准数,比该数小的数放置于左侧,比该数大的数放置于右侧,然后将左右两侧的数分别找出两个标准,分别分出左侧的左侧与右侧以及右侧的左侧与右侧,再分,直到分到标准数的左右侧为标准数本身,此时序自然就排好了。

按该思想,需要进行循环操作,若使用正常循环(for,while)则十分麻烦,所以选择递归算法,递归趋势是减小数组的范围(如左侧的左边界为标准数,右侧为最大的数),停止递归的条件是边界内只有一个值。

按上例:a[5]={41,23,57,18,47},选择41为标准值,将所有数与41对比,得到右侧值为57,47,左侧值为23,18,将41置于两部分间,调用函数继续分割,左侧选择23为标准值,18小于23,置于新的左侧,结束。在右侧,选择57作为新标准,47比57小,置于新左侧,结束。此时再看左侧的新左侧,选择18作为标准值,其左右都无值,结束递归,再看其他部分,若类似,就结束递归,若有值,就继续递归,直到条件符合结束递归的条件。

代码如下:

#include<stdio.h>
int fun(int *a,int low,int high)
{
    int i=low;
    int j=high;
    int t=a[low];
    if(i>=j)
    {
    return 0;
    }
    while(i<j)
    {       
         while(i<j &&a[j]>=t)
        {
            j--;
        }
        a[i]=a[j];
        while(i<j&&a[i]<t)
        {
            i++;
        }
        a[j]=a[i];
    }
    a[i]=t;
    fun(a,i+1,high);
    fun(a,low,i-1);
}
int main(void)
{
    int a[5]={41,23,57,18,47};
    int len=sizeof(a)/sizeof(int);
    fun(a,0,len);
for(int i=0;i<len;i++)
{
    printf(" %d",a[i]);
}
}

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值