排序算法(C语言)

排序之比较排序
这里写图片描述
1.冒泡排序

#include <stdio.h>
/*冒泡排序*/
/*设数组长度为N。

1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。

2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。

3.N=N-1,如果N不为0就重复前面二步,否则排序完成。*/
void swap(int * Num1,int * Num2)
{
        int p=*Num1; // “*”是取值, “&”是取地址 
        *Num1=*Num2;
        *Num2=p;
}
void BubbleSort(int Data[],int N) 
{
    int i,j; 
        for(i=0;i<N;i++)    //总共需要遍历N次 
            for(j=1;j<N-i;j++)  //遍历第i次时,从第N-i个元素开始,之后的元素均以排好队(如第一遍便利完成后,最大的元素在最后) 
                if(Data[j]<Data[j-1])
                    swap(&Data[j],&Data[j-1]);  //传递地址进去进行交换 
}
int main(void)
{
    int Data[13]={ 81,94,11,96,12,35,17,95,28,58,41,75,15};
    int i;
    BubbleSort(Data,13);
    for(i=0;i<13;i++)
    printf("%d ",Data[i]);
    return 0;   
}

2.直接插入排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*直接插入排序*/
/*每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,
直到全部记录插入完成为止。
设数组为a[0…n-1]。

1.      初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1

2.      将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。

3.      i++并重复第二步直到i==n-1。排序完成。*/

 void swap(int * Num1,int * Num2)
{
        int p=*Num1; // “*”是取值, “&”是取地址 
        *Num1=*Num2;
        *Num2=p;
}
 void Insertsort(int  Data[],int N)
 {
    int i,j;
    for(i=1;i<N;i++)  //N个元素需要N次才能读入 
    {   
        for(j=i-1;j>=0 && Data[j]>Data[j+1];j--)  //每读入一个元素就在之前排好序的数组中插入到合适的位置 
        swap(&Data[j],&Data[j+1]);
     }  
 } 
 int main(void)
{
    int Data[13]={ 81,94,11,96,12,35,17,95,28,58,41,75,15 };
    int i;
    Insertsort(Data,13);
    for(i=0;i<13;i++)
    printf("%d ",Data[i]);
    return 0;   
} 

3.直接选择排序

#include <stdio.h>
/*直接选择排序*/
/*
将数据分为有序区和无序区,从无序区选一个最小的元素直接放到有序区的最后。
设数组为a[0…n-1]。

1.      初始时,数组全为无序区为a[0..n-1]。令i=0

2.      在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交换。交换之后a[0…i]就形成了一个有序区。

3.      i++并重复第二步直到i==n-1。排序完成。
*/

void swap(int* a,int* b)
{
        if(*a!= *b)
        {
                *a^=*b;
                *b^=*a;
                *a^=*b;
        }

}
void Selectsort(int Data[],int N)
{
        int i,j,MinIndex;
        for(i=0;i<N;i++)
        {
                MinIndex = i;
                for(j=i+1;j<N;j++)
                {
                        if(Data[j]<Data[MinIndex])  //选择无序区的最小元素,类似冒泡排序 
                        MinIndex = j;
                }
                        swap(&Data[i],&Data[MinIndex]);
        }
}
void display(int Data[],int N)
{
        int i;
        for(i=0;i<N;i++)
        {
                printf("%d ",Data[i]);
        }
        printf("\n");
}
int main(void)
{
        int Data[13]={ 81,94,11,96,12,35,17,95,28,58,41,75,15 };
        display(Data,13);
        Selectsort(Data,13);
        display(Data,13);
        return 0;
}

4.希尔排序

#include <stdio.h>
/*希尔排序*/
/*先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)
分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序
(增量足够小)时,再对全体元素进行一次直接插入排序。*/

 void swap(int * Num1,int * Num2)
{
        int p=*Num1; // “*”是取值, “&”是取地址 
        *Num1=*Num2;
        *Num2=p;
}
void Shellsort(int Data[],int N)
{
    int i,j,Increament;
    unsigned char Tmp;
    for(Increament = N/2;Increament > 0;Increament /= 2) //分割子序列 
    {
        for(i=Increament;i<N;i++)   //分别直接插入 
        {
            Tmp = Data[i];
            for(j=i-Increament;j>=0 && Data[j] > Data[j+Increament];j-=Increament)
                swap(&Data[j],&Data[j+Increament]);
        }
    }
    for(i=0;i<N;i++)
    printf("%d\n",Data[i]);
}
int main (void)
{
    unsigned int Data[13]={81,94,11,96,12,35,17,95,28,58,41,75,15};
    Shellsort(Data,13);  //此处传入数组名 
    return 0;
}

5.堆排序

#include<stdio.h>
/*
    堆排序:
        ①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。
        建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 
        其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。
        ②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。
        利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,
        如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,
        这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,
        因为是沿着深度方向进行调整的。
        ③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。
        然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,
        然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。
        因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,
        所以堆排序的时间复杂度是O(nlgn)
*/
void swap(int * Num1, int * Num2)
{
    int p = *Num1; // “*”是取值, “&”是取地址 
    *Num1 = *Num2;
    *Num2 = p;
}
void AdjustHeap(int* Data, int i,int num)
{
    int Child=2*i+1;  //左儿子的下标
    int Tmp=Data[i];  //父节点
    for (; Child < num;i=Child)//未越界
    {
        if (Child<num-1 && Data[Child] < Data[Child + 1])   //若有儿子大于父亲则调换父亲与最大儿子的位置
            Child++;                        //左儿子大且大于父节点                
                                            //当左儿子小于右儿子时,需要将儿子的下标+1得到有儿子的下标
        if (Data[Child] > Tmp)              //右儿子最大且大于父节点
            swap(&Data[i], &Data[Child]);           //右儿子与父节点调换
        else                                //父节点大于子节点,不用调换
            break;
    }
    Data[i] = Tmp;
}

void HeapSort(int* Data, int num)
{
    int i;
    for (i = num / 2; i >= 0; i--)
        AdjustHeap(Data, i, num);
    for (i = num - 1; i > 0; i--)//删除总是发生在根Data[0]处,表中最后一个元素用来填补空缺
    {
        swap(&Data[0], &Data[i]);
        AdjustHeap(Data, 0, i);
    }
}
int main(void)
{
    int Data[13] = { 81,94,11,96,12,35,17,95,28,58,41,75,15 };
    int i;
    HeapSort(Data, 13);
    for (i = 0; i<13; i++)
        printf("%d ", Data[i]);
    return 0;
}

6.归并排序

#include<stdio.h>
#include<stdlib.h>
/*
    归并排序:
        比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;
        否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,
        直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
        归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,
        再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
*/
void Merge(int* Data, int* Array, int left, int cen, int right)//合并:第一个:Data[left~cen];第二个[cen+1~right]
{
    int i = left; //第一个
    int j = cen + 1;
    int n = cen;
    int m = right;
    int k=0;
    while (i <= n && j <= m)  //选择小的先插入
    {
        if (Data[i] < Data[j])
            Array[k++] = Data[i++];
        else
            Array[k++] = Data[j++];
    }
    while (i <= n)  //剩下的直接插入
        Array[k++] = Data[i++];
    while (j <= m)
        Array[k++] = Data[j++];
    for (i = 0; i < k; i++)
        Data[left + i] = Array[i];
}
void MSort(int* Data, int* Array, int left, int right)//递归排序
{
    int cen;
    if (left < right)
    {
        cen = (left+right) / 2;
        MSort(Data,Array,left,cen);
        MSort(Data, Array,cen+1,right);
        Merge(Data, Array, left, cen, right);
    }
}
void MergeSort(int* Data,int num)
{
    int* Array ;
    Array = (int*)malloc(num * sizeof(int));
    if (Array == NULL)
        printf("Error!!!\n");
    else
    {
        MSort(Data, Array, 0, num - 1);
        free(Array);
    }
}
int main(void)
{
    int Data[13] = { 81,94,11,96,12,35,17,95,28,58,41,75,15 };
    int i;
    MergeSort(Data, 13);
    for (i = 0; i<13; i++)
        printf("%d ", Data[i]);
    return 0;
}

7.快速排序
/参考链接:http://developer.51cto.com/art/201403/430986.htm/

#include <stdio.h>
/*
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,
使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
*/
void swap(int * Num1, int * Num2)
{
    int p = *Num1; // “*”是取值, “&”是取地址 
    *Num1 = *Num2;
    *Num2 = p;
}
int Median3(int* Data, int left, int right)//三数中值分割法
{
    int mid = (left + right) / 2;
    if (Data[left] > Data[mid])  //先将left,mid,right顺序先排号
        swap(&Data[left], &Data[mid]);
    if (Data[left] > Data[right])
        swap(&Data[left], &Data[right]);
    if (Data[mid] > Data[right])
        swap(&Data[mid], &Data[right]);
    swap(&Data[mid], &Data[right - 1]);
    return Data[right - 1];
}
void QuickSort(int* Data, int left,int right)
{
    int i, j;
    int key;
    if (left + 3 <= right)
    {
        key = Median3(Data, left, right);
        i = left;
        j = right;
        for (; ; )//排序核心
        {
            while (Data[i++] < key) {}//将比key小的数都放在key之前
            while (Data[j--] > key) {}//将比key大的数都放在key之后
            if (i < j)  //若i处的数大于可以key,而j处的数小于key则交换两个数
                swap(&Data[i], &Data[j]);
            else
                break;
        }
        swap(&Data[i], &Data[right - 1]);  //将key归位
        QuickSort(Data, left, i - 1);
        QuickSort(Data, i + 1, right);
    }
    else
        printf("Error!\n");
}
int main(void)
{
    int Data[13] = { 81,94,11,96,12,35,17,95,28,58,41,75,15 };
    int i;
    QuickSort(Data, 0,13);
    for (i = 0; i<13; i++)
        printf("%d ", Data[i]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值