6种基础排序算法的理解(更新中)

本文详细介绍了五种经典的排序算法:冒泡排序、插入排序、选择排序、希尔排序及快速排序,并给出了每种算法的实现代码及核心思想。此外,还简要提到了归并排序的实现方法。

排序实现功能,将数组从大到小排序。

代码:https://github.com/Fu4ng/Cpp/blob/master/sort.cpp

1.冒泡排序


冒泡排序(Bubble sorting)像是一个泡泡冒出海面,完成排序。但这样描述很飘渺,特别是和插入排序(Insert sorting)对比。这两种算法太像了。冒泡排序将后一个元素与前面的元素逐次比较,将最大(小)的值移到左(右)端。 先看代码

void Bubblesorting(int arr[],int n)
{   //冒泡排序 
    for(int a=0;a<n-1;a++)
    {
        for(int b=n-1;b>a;b--)
        {
            if(arr[b]>arr[b-1]) swap(arr[b-1],arr[b]);
         } 
    }
}

如果我们有一个数组 1,2,3,4
那么第一次循环,数字4 就是泡泡(因为我们从第n-1个元素开始循环)。当“4”不断和相邻的数字交换最后跑到“1”的前面,那么就算“4”的冒泡之旅完成了。下一次循环,我们就从“3”开始冒泡。(因为2在上一次循环时与1交换位置,成为了第n-1个元素。)

2.插入排序


插入排序也是通过于相邻的元素进行交换从而进行排序的。但是插入排序的思想与冒泡不同。 始终定义第一个元素是已排序的数组,然后不断扩大数组,然后腾出位置给“插入进来的元素”

void Insetsorting(int arr[],int n)
{
    for(int a= 1;a<n;a++)
    {
        for(int b=a ; b>0 ;b--)
        {
        if(arr[b]>arr[b-1]) swap(arr[b],arr[b-1]);
        }
    }
 } 

还是 1,2,3,4的数组
插入排序的思想是
先将1,2排序成正序序列{2,1},而未排序的{3,4},在下次循环中插入到已排序的序列中。
{{3,2,1},{4}}
把插入排序的数组就像你拿着一副排好的牌,然后从牌组抽牌,然后把抽的牌插入你手里的牌里。

3.选择排序

选择排序就是假设第一个元素带着一个“最大值”的王冠跟其他元素比较,如果某个元素比他大,他就要把“最大值”王冠让给他,然后这个带着王冠的元素要就与其他元素比较。如果比了一圈,还是他最大,他就退隐山林(移到数组第一个元素的位置)把王冠让出来,然后让剩下的元素继续比较。

 void Selectionsorting(int arr[],int n)
 {
    for(int a =0;a<n;a++)
    {
        int bigest = a;
        for(int b = a+1;b<n;b++)
        {
            if(arr[bigest]<arr[b])
            swap(arr[bigest],arr[b]);
        }
         cout<<arr[bigest]<<",";//输出最大值
     }
 }

4.希尔排序(shellsorting)

希尔排序是插入排序的变体,但效率比插入排序有较大的提升。步长为2的shell排序的时间代价可以达到θ(n的3/2次方),有的增量可以达到θ(n的7/6次方),很接近θ(n)
将一个无序的数组,以步长为单位看成几个子数组,在对子数组分别排序,然后再缩短步长,在进行排序,最后步长缩小至1,也就是相邻对比,完成排序。
插入循环的在最优情况下,就是对一个已经排好序的数组进行排序的时候,时间复杂度是O(n),也就是不进行交换。希尔排序就是把数组局部调换,一步步变成一个接近有序的数组,最后在插入排序,一步搞定。

 void Shellsorting (int arr[],int n)
 {
    for(int delta=n/2;delta>0;delta/=2)
    {   //delta 为步长
        for(int a =delta;a<n;a++)
        {
            for(int b=a-delta;b>=0;b-=delta)
            {   if(arr[b]<arr[b+delta])
                swap(arr[b],arr[b+delta]);
            }
        }

还有快速排序,归并排序,之后再更把。。脖子酸。。。。去操场走一走

3.12 新增快速排序

5.快速排序


快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用。思想大概就是:
在一个无序数组中找到一个基准数,然后把比基准数大的数放到右边,比其小的放到左边。然后再对基准数两边的无序数组进行快速排序(递归)。
这里用语言有点难表达,上一张图,来自
http://blog.csdn.net/morewindows/article/details/6684558

这里写图片描述

这里写图片描述

void Quicksorting(int arr[],int left,int right)
{
    if(left>right)
    return ;
    int a,b;
    a=left;
    b=right;
    int key = arr[left];//key 为基准数
    while(a!=b) 
    {
        while(a<b&&arr[b]<=key)
            b--;
        while(a<b&& arr[a]>=key)
            a++;
        if(a<b)
            swap(arr[a],arr[b]);

     } 
     arr[left]=arr[a];  //防止相同的数
     arr[a]=key;
     //递归部分
     Quicksorting(arr,left,a-1);
     Quicksorting(arr,a+1,right); 
 } 

如果要实现程序确定left和right的值的话,有一点要注意。
left值一般是从0开始,而right= size(arr)/size(0) -1
记得-1 否则内存越界。因为从0开始计数。

6.归并排序

代码实现图
代码

 void MemeryArray(int *arr,int first,int mid,int last )
{   //归并算法—分解部分
    //将数组分解成两个临时数组
    int numOfTemp1 = mid - first+1;
    int numOfTemp2 = last -mid;
    int *Temp1 =new int [numOfTemp1+1];
    int *Temp2 =new int [numOfTemp2+1];
    int i =0 , j=0 ,k=0;
    while(i<numOfTemp1)
    {
        Temp1[i]=arr[first+i];
        i++;
    }
    while(j<numOfTemp2) 
    {
        Temp2[j]=arr[mid+j+1];
        j++;
    }

    Temp1[numOfTemp1]=10000;
    Temp2[numOfTemp2]=10000;
    //定义这两个数值是因为上面FOR循环不能循环到numOfTemp项,而系统会给他们随便赋值,所以要给一个大过所有数的数值。
    //归并算法—合并部分
    for(i=0,j=0,k=first;k<=last;k++)
    {
        if(Temp1[i]<=Temp2[j])
        {
            arr[k]=Temp1[i];
            i++;
        }
        else
        {
            arr[k]=Temp2[j];
            j++;
        }
    }
    delete[]Temp1;             //重置指针
    delete[]Temp2; 


}
void Mergesorting(int *arr,int first,int last)
{
    if(first<last)
    {
        int mid =(first+last)/2;
        Mergesorting(arr,first,mid);
        Mergesorting(arr,mid+1,last);
        MemeryArray(arr,first,mid,last);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值