c实现的各种排序

虽然以前学习Java的时候对各种排序都进行学习和掌握,自己觉得也挺简单,每次用到的时候,都是去copy书上或者网上现成的,这两天在准备C语言考试的时候,才发现自己踏踏实实一行一行敲出来的代码运行不出正确结果来。当时就忍不了了。好多招聘面试都是开口就问数据结构的知识,而数据结构里面最简单的就是各种排序,这要不先搞定,就没法玩了。所以决定重新温习一遍。(这里全是以升序来讲解的,降序只需更改比较大小的那句代码就行)

但是在讲排序之前呢,不得不说说swap函数的写法,如果是值传递的话交换不会成功。如下:

void swap(int a, int b )
{ 
    int temp=a;
    a=b;
    b=temp;
}       

为什么呢,因为这里实参和形参拥有不同的内存空间,在执行的时候是把实参先复制到形参的内存空间中去,在swap里面只是对形参进行了交换,而我们真正想交换的实参数据却没有任何改变。

所以可以用传地址(即指针)的方式来进行交换,这样就都是对同一内存空间进行操作了。

void swap(int *p1, int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

1、选择排序
所谓选择,顾名思义就是以选择的方式,即每次通过比较选出一个最小的数的索引,然后把该索引处的数组元素放到适当位置。代码如下:

void select(int a[], int len)
{
    int i, j, index;
    for(i=0; i<len; i++)
    {
        index=i;
        for(j=i+1; j<len; j++)
            if(a[j]<a[index])
                index=j;
        swap(a+i, a+index);
    }
}

2、插入排序
插入排序的思路是每次把一个数插入到已排好序的序列里面去,例如,一开始我们把数组的第一个元素看做已排好的序列(尽管只有一个元素),然后把数组的第二个元素通过比较插在该序列的适当位置,以此类推,当做第n次插入的时候,那么前n-1个数就已经是排好序的了。代码如下:

void insert(int a[], int len)
{
    int i, j, temp;
    for(i=1; i<len; i++)
    {
        if(a[i]<a[i-1])
        {
            temp=a[i];
            j=i;
            while(j>0 && a[j-1]>temp)
            {
                a[j]=a[j-1];
                j--;
            }
            a[j]=temp;
        }
    }
}

3、冒泡排序
对于冒泡排序个人觉得是最好理解也是最好写的,四行代码就搞定了。不过还是说说这个过程吧,从开头依次进行两两比较,判断是否交换,所以一次冒泡的结果就是得到一个最大的放在末尾。代码如下:

void bubble(int a[], int len)
{
    int i, j;
    for(i=len-1; i>=0; i--)
        for(j=0; j<i; j++)
            if(a[j]>a[j+1])
                swap(a+j, a+j+1);
}

4、快速排序
快速排序采用递归的思想,就是先取一个参考值,通过一趟排序将要排序的数据分割成独立的两部分,把比参考值小的放到其前面,比参考值大的放到其后面,然后再按此方法对这两部分数据分别进行快速排序。代码如下:

void quick(int a[], int len)
{
    int i=0, j=len-1;
    int val=a[0];
    if(len>1)
    {
        while(i<j)
        {
            for(; j>i; j--)
                if(a[j]<val)
                {
                    a[i++]=a[j];
                    break;
                }
            for(; i<j; i++)
            {
                if(a[i]>val)
                {
                    a[j--]=a[i];
                    break;
                }
            }
        }
    }
    a[i]=val;
    quick(a, i);
    quick(a+i+1, len-i-1);
}

5、归并排序
归并排序的基本思路是,将数组分成 两组A,B,如果这两组组内的数据都是有序的,那么就可以很方便的将这两组数据进行排序。如何让这两组组内数据有序?可以将A,B组各自再分成两组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的两个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。代码如下:

/*复制数组,source:源数组,dest:目标数组,len:源数组长度,
  first:目标数  组起始位置  */
void copy(int source[], int dest[],int len,int first)  
{  
    int i;  
    int j=first;  
    for(i=0;i<len;i++)  
    {  
        dest[j] = source[i];  
        j++;  
    }  
}

//归并过程
void merge(int a[],int left,int right)  
{  
    int begin1 = left;  
    int mid = (left+right)/2 ;  
    int begin2 = mid+1;  
    int k=0;  
    int newArrayLen = right-left+1;  
    int *b = (int*)malloc(newArrayLen*sizeof(int));  
    while(begin1<=mid && begin2<=right)  
    {  
        if(a[begin1]<=a[begin2])  
            b[k++] = a[begin1++];  
        else  
            b[k++] = a[begin2++];  
    }  
    while(begin1<=mid)  
        b[k++] = a[begin1++];  
    while(begin2<=right)  
        b[k++] = a[begin2++];  
    copyArray(b,a,newArrayLen,left);  
    free(b);  
}  
//递归调用
void mergeSort(int a[],int left,int right)  
{  
    int i; 
    if(left < right)  // 保证至少有两个元素 
    {  
        i = (left+right)/2;  
        mergeSort(a,left,i);  
        mergeSort(a,i+1,right);  
        merge(a,left,right);  
    }  
}  
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页