数据结构:排序

来源:互联网 发布:淘宝水果店铺装修 编辑:程序博客网 时间:2024/06/06 13:16

目前就举例出我所学会的几种算法,并且都是对于内排序而言。

冒泡排序

1.  代码如下:

void bubble_sort_init(int a[SIZE]){    int i,j;    for(i=0;i<SIZE-1;i++)    {        for(j=i+1;j<SIZE;j++)        {            if(a[i]>a[j])                swap(a[i],a[j]);        }    }}
大循环控制从下标0开始,往下对比,当对比倒到有比a[0]小的,立马交换两个数的值;照例推,之后寻找出第二小,第三小的。。。。。。

效率太低,而且称不上冒泡,故有了新的改进算法

2. 代码如下:

void bubble_sort_up(int a[SIZE]){    int i,j;    for(i=0;i<SIZE-1;i++)    {        for(j=SIZE-1;j>i;j--)        {            if(a[j-1]>a[j])                swap(a[j-1],a[j]);        }    }}
从数组底部开始,一个个小的往上面冒,当然,也可以一个个大的往下面沉。

3:优化后最终的代码
想一想,如果某一次大循环进行了一次比较,然而没有顺序不合理的,于是乎可以不用再进行下面其余的循环,故增设一个flag标志。

void bubble_sort_end(int a[SIZE]){    int i,j;    int flag=1;//初始为1    for(i=0;i<SIZE-1&&flag;i++)    {        flag=0;        for(j=SIZE-1;j>i;j--)        {            if(a[j-1]>a[j])                swap(a[j-1],a[j]);                flag=1;//本次循环依旧有数据之间的转移        }    }}

每次进入循环都认作并未进行排序,一旦没有进行过交换,则flag为0,则下次就不需要再进行循环冒泡比较了;

选择排序

void bubble_sort_end(int a[SIZE]){    int i,j;    int min;//初始为1    for(i=0;i<SIZE-1;i++)    {        min=i;        for(j=i+1;j>SIZE;j++)        {            if(a[min]>a[j])                min=j;            if(min!=i)                swap(a[i],a[min]);        }    }}


插入排序

基本思想

每步将一个待排序的对象,按其排序码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止


直接插入排序

#include<stdio.h>#define SIZE    10int a[]={1,4,2,3,4,0,7,6,4,9};void swap(int i,int j){    int temp=a[i];    a[i]=a[j];    a[j]=temp;}void insert_sort(int a[SIZE]){    int i,j;    for(i=1;i<SIZE;i++)    {        if(a[i]<a[i-1])        {               for(j=i-1;a[j+1]<a[j];j--)                swap(j+1,j);        }    }}void main(){    int i=10;    while(i--)    printf("%d ",a[9-i]);    putchar('\n');    i=10;    insert_sort(a);    while(i--)    printf("%d ",a[9-i]);}

程序运行结果如下:

1 4 2 3 4 0 7 6 4 9
0 1 2 3 4 4 4 6 7 9
Process returned 0 (0x0)   execution time : 0.302 s
Press any key to continue.
最开始直接让a[0]为已经插好的数据,接着继续处理之和的第二个,也就是a[1];当后面未排序的小于前面已经排好序的则不停地swap往前挪,最终找到合适位置。同理,当新加未排序元素大于之前的元素,则不需排序,因为前面的元素更小,不用比较。


快速排序
#include <stdio.h> int a[101],n;//定义全局变量,这两个变量需要在子函数中使用 void quicksort(int left,int right) {     int i,j,t,temp;     if(left>right)        return;                                     temp=a[left]; //temp中存的就是基准数     i=left;     j=right;     while(i!=j)     {                    //顺序很重要,要先从右边开始找                    while(a[j]>=temp && i<j)                             j--;                    //再找左边的                    while(a[i]<=temp && i<j)                             i++;                    //交换两个数在数组中的位置                    if(i<j)                    {                             t=a[i];                             a[i]=a[j];                             a[j]=t;                    }     }     //最终将基准数归位     a[left]=a[i];     a[i]=temp;                                  quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程     quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程 } int main() {     int i,j,t;     //读入数据     scanf("%d",&n);     for(i=1;i<=n;i++)                    scanf("%d",&a[i]);     quicksort(1,n); //快速排序调用                                  //输出排序后的结果     for(i=1;i<=n;i++)         printf("%d ",a[i]);     getchar();getchar();     return 0; } 
该算法或许会有些疑问,比如“为什么要哨兵j先走

答案:因为如果哨兵i先走,i和j相遇的时候,i和j所在位置的数会是一个大于基准数的数,这时基准数在最左边,这个数再和基准数位置交换,那么基准数左边就有一个大于基准数的数了,这样就达不到目的了(左边全部小于基准数,右边全部大于基准数)
我们解剖一下其原理:

什么时候结束小循环呢?不外乎三种情况

1:正常的结束,j找到一个小于基准数的值,i找到一个大于j的值,之后二者交换,此时排序未接近尾声。

2:当j不停的减一直到找到一个小于基准数的值,此时i继续走,最后由于没有大于基准数的值,所以i=j,跳出所有循环,此时i和j所对应的都为一个小于基准数的元素,所以两者交换,排序完成。

 但是另一种情况,j一直未找到小于基准数的值,直到i=j了,此时直接跳出所有循环和判断语句,但是我们知道,上一个循环结束的i对应的元素必是小于i的,所以,j=i其实已经对应着一个小于基准数的值,所以直接交换完成排序。

以上是目前我用过的几种排序。

原创粉丝点击