八大排序算法及代码

1.插入排序

(1)直接插入排序
从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤2~5。
原始序列:49 38 65 97 13 27 49
第1次: 38 49 65 97 13 27 49
第2次: 38 49 65 97 13 27 49
第3次: 38 49 65 97 13 27 49
第4次: 13 38 49 65 97 27 49
第5次: 13 27 38 49 65 97 49
第6次: 13 27 38 49 49 65 97
时间复杂度O(n2)
代码:

/*直接插入排序*/
void insertSort(int list[], int n)
{
    int i = 1, j = 0, node = 0, count = 1;
    printf("对序列进行直接插入排序:\n");
    printf("初始序列为:");
    printList(list, n);
    for(i = 2; i <= n; i++)
    {
        node = list[i];
        j = i - 1;
        while(j >= 0 && node < list[j])
        {
            list[j+1] = list[j];
            --j;
        }
        list[j+1] = node;
        printf("第%d次排序结果:", count++);
        printList(list, n);
    }
}

(2).折半插入排序
设待排序的记录存放在数组r[1…n]中,r[1]是一个有序序列。
循环n-1次,每次使用折半查找法,查找r[i](i=2,…,n)在已排好的序列r[1…i-1]中的插入位置,然后将r[i]插入表长为i-1的序列r[1…i-1],直到将r[n]插入表长为n-1的有序序列r[1…n-1],最后得到一个表长为n的有序序列。
时间复杂度仍为O(n2)

void BinsertSort(int slist[],int n)
{
    int i,j,low,high,mid,node;
    for(int i=2; i<=n; i++)
    {
        node=slist[i];
        low=1;
        high=i-1;
        while(low<=high)
        {
            mid=(low+high)/2;
            if(node<slist[mid])
                high=mid-1;
            else
                low=mid+1;
        }
        for(j=i-1; j>=low; j--)
            slist[j+1]=slist[j];
        slist[low]=node;
        printf("第%d次排序结果:", cnt++);
        printList(slist, n);
    }
}

2.希尔排序

选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
按增量序列个数k,对序列进行k 趟排序;
每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
在这里插入图片描述
过程:(48 16 92 65 32 65 27 23)
1.首先,增量d1=4,将序列分割为4个子序列,{R1,R5}{R2,R6}{R3,R7}{R4,R8}分别对每个子序列插入排序
2.增量d2=2,分别对两个子序列{R1,R3,R5,R7}{R2,R4,R6,R8}进行直接插入排序
3.增量d3=1,对整个记录进行一次直接插入排序。
代码:

void ShellSort(int slist[],int n)   //希尔排序
{
    int i,j,d;
    for(d=n/2; d>0; d/=2)
    {
        for(i=d+1; i<=n; i++)
        {
            if(slist[i]<slist[i-d])
            {
                slist[0]=slist[i];
                for(j=i-d; j>0&&slist[j]>slist[0]; j-=d)
                    slist[j+d]=slist[j];
                slist[j+d]=slist[0];
            }
        }
        printf("第%d次排序结果:", count++);
        printList(slist, n);
    }
}

3.冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换它们两个;
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
针对所有的元素重复以上的步骤,除了最后一个;
重复步骤1~3,直到排序完成。

void BubbleSort(int list[],int n)  //冒泡排序
{
    int i,j,flag,temp;
    for(j=1; j<=n-1; j++)
    {
        flag=0;
        for(i=1; i<=n-j; i++)     //对无序区扫描
        {
            if(list[i]>list[i+1])
                flag=1,temp=list[i],list[i]=list[i+1],list[i+1]=temp;    
       }
        if(flag==0)    //本趟排序未交换,提前终止算法
            break;
        printf("第%d次排序结果:", count++);
        printList(list,n);
    }
    return ;
}

4.快速排序

1.初始化:取第一个记录R1作为枢纽,设置两个指针i,j分别用来指示将要与基准进行比较的左侧记录和右侧记录的位置。
2.用枢纽记录与j指向的记录比较,如果j指向的比枢纽大,j减1,继续比较,直到比枢纽小,那么将j指向的记录移动到i所指的位置。
3.用枢纽记录与指针i+1指向的记录比较,如果i指向的记录的关键字值小,则i+1,继续比较,直到i指向的记录的关键字值比枢纽记录大,那么将i指向的记录移动到j指向的位置。
4.重复2和3,直到i==j,这时候i就是枢纽的最终位置。
初始序列: 46 16 89 65 34 65 23 28
第一次移动:28 16 89 65 34 65 23
第二次移动:28 16 65 34 65 23 89
第三次移动:28 16 23 65 34 65 89
第四次移动:28 16 23 34 65 65 89
第五次移动:28 16 23 34 65 65 89
第一趟快排:28 16 23 34 46 65 65 89
第二趟快排:23 16 28 34 46 65 65 89
第三趟快排:16 23 28 34 46 65 65 89
第四趟快排:16 23 28 34 46 65 65 89
第五趟快排:16 23 28 34 46 65 65 89
当初始序列基本有序时,退化成冒泡排序,快排的平均时间复杂度为O(nlog2n)
代码:

void quick_sort(int a[],int l,int r,int n) //快速排序
{
    int k=a[l];
    if(l<r)
    {
        int i=l,j=r;
        while(i<j)
        {
            while(a[j]>=k&&i<j) j--;
            a[i]=a[j];
            while(a[i]<=k&&i<j) i++;
            a[j]=a[i];
        }
        a[i]=k;
        printf("第%d次排序结果:", count++);
        printList(a,n);
        quick_sort(a,l,i-1,n);    //递归左区间
        quick_sort(a,i+1,r,n);   //递归右区间
    }
}

5.选择排序

每经过一次比较就找出一个最小值,与待排序序列最前面的位置互换即可。
代码:

void SelectSort(int a[],int n)   //选择排序
{
    int i,j,minn;
    int temp;
    for(i=1;i<n;i++)
    {
        minn=i;
        for(j=i+1;j<=n;j++)
            if(a[i]>a[j])
              minn=j;
        if(minn!=i)
           temp=a[i],a[i]=a[minn],a[minn]=temp;
        printf("第%d次排序结果:", count++);
        printList(a,n);
    }
    return ;
}

6.堆排序

堆:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

过程:将n个无序的记录建成一个堆,此时选出堆中所有记录的最大值或最小值,然后输出堆顶元素,(每次都用堆顶元素和最后一个非终端节点开始逐步往前交换)将剩余的n-1个元素重新建成一个堆,输出次大值。
在这里插入图片描述
在这里插入图片描述
代码:

/*堆排序*/
void heapAdjust(int list[], int u, int n)
{
    int node=list[u];
    for(int j=2*u; j<=n; j*=2)      //向下筛选
    {
        if(list[j]<list[j+1]&&j+1<=n)
            j++;   //j为左右孩子中较大的那个的下标
        if(node>list[j])
            break;
        list[u]=list[j];     //调整到位
        u=j;
    }
    list[u]=node;
}
void heapSort(int list[], int n)
{
    int i,temp;
    printf("请输出初始堆:");
    for(i=n/2; i>0; i--)
        heapAdjust(list,i,n);  
    //要使每个非终端结点都大于他的左右孩子,直到根节点为止,n个节点的完全二叉树的最后一个非终端节点编号必为n/2,所以从下标为n/2的节点开始调整,建成大根堆
    printList(list,n);
    for(i=n; i>1; i--)
    {
        temp=list[i];
        list[i]=list[1];
        list[1]=temp;    //堆顶与堆底交换
        printf("第%d次排序结果:", count++);
        heapAdjust(list,1,i-1);    //重建堆
        printList(list,n);
    }
}

7.归并排序

过程:假设初始序列含有n个记录,可看成有n个有序子序列,每个子序列长度为1,然后两两归并,得到n/2个长度为2的子序列,再两两归并,一直到得到一个长度为n的有序表为止。归并排序需要一个数组来存改变后的状态。
时间复杂度为O(nlog2n)
在这里插入图片描述
代码:

void Merge(int a[],int l,int r,int m,int n)
{
    int i=l,j=m+1,k=l;
    int temp[MAX];
    while(i<=m&&j<=r)
    {
        if(a[i]>a[j])
            temp[k++]=a[j++];
        else
            temp[k++]=a[i++];
    }
    while(i<=m)
        temp[k++]=a[i++];
    while(j<=r)
        temp[k++]=a[j++];
    for(i=l;i<=r;i++)
        a[i]=temp[i];
     printf("第%d次排序结果:", count++);
    printList(a,n);
}
void MergeSort(int a[],int l,int r,int n) //归并排序
{
    if(l<r)
    {
        int mid=(l+r)/2;
        MergeSort(a,l,mid,n);    //递归分成只有1个数的小区间
        MergeSort(a,mid+1,r,n);
        Merge(a,l,r,mid,n);
    }

}

8.基数排序

通过基数排序对数组{53, 3, 542, 748, 14, 214, 154, 63, 616},它的示意图如下:
在这里插入图片描述
在上图中,首先将所有待比较树脂统一为统一位数长度,接着从最低位开始,依次进行排序。

  1. 按照个位数进行排序。
  2. 按照十位数进行排序。
  3. 按照百位数进行排序。
    排序后,数列就变成了一个有序序列。
    代码还不会写~
排序方法时间复杂度空间复杂度稳定性
直接插入排序O(n2)O(1)稳定
希尔排序O(n1.3)O(1)不稳定
简单选择排序O(n2)O(1)不稳定
堆排序O(nlog2n)O(1)不稳定
冒泡排序O(n2)O(1)稳定
快速排序O(nlog2n)O(log2n)~O(n)不稳定
归并排序O(nlog2n)O(n)稳定
基数排序O(d(n+r))O(n+r)稳定

七种排序的代码及调用

#include <stdlib.h>
#include <stdio.h>
#include<algorithm>
#define MAX 50

int slist[MAX]; /*待排序序列*/
int count;
void insertSort(int list[], int n);
void createList(int list[], int *n);
void printList(int list[], int n);
void heapAdjust(int list[], int u, int v);
void heapSort(int list[], int n);

/*直接插入排序*/
void insertSort(int list[], int n)
{
    int i = 1, j = 0, node = 0, count = 1;
    printf("对序列进行直接插入排序:\n");
    printf("初始序列为:");
    printList(list, n);
    for(i = 2; i <= n; i++)
    {
        node = list[i];
        j = i - 1;
        while(j >= 0 && node < list[j])
        {
            list[j+1] = list[j];
            --j;
        }
        list[j+1] = node;
        printf("第%d次排序结果:", count++);
        printList(list, n);
    }
}
/*堆排序*/
void heapAdjust(int list[], int u, int n)
{
    int node=list[u];
    for(int j=2*u; j<=n; j*=2)
    {
        if(list[j]<list[j+1]&&j+1<=n)
            j++;
        if(node>list[j])
            break;
        list[u]=list[j];
        u=j;
    }
    list[u]=node;
}
void heapSort(int list[], int n)
{
    int i,temp;
    printf("请输出初始堆:");
    for(i=n/2; i>0; i--)
        heapAdjust(list,i,n);
    printList(list,n);
    for(i=n; i>1; i--)
    {
        temp=list[i];
        list[i]=list[1];
        list[1]=temp;
        printf("第%d次排序结果:", count++);
        heapAdjust(list,1,i-1);
        printList(list,n);
    }
}
void ShellSort(int slist[],int n)   //希尔排序
{
    int i,j,d;
    for(d=n/2; d>0; d/=2)
    {
        for(i=d+1; i<=n; i++)
        {
            if(slist[i]<slist[i-d])
            {
                slist[0]=slist[i];
                for(j=i-d; j>0&&slist[j]>slist[0]; j-=d)
                    slist[j+d]=slist[j];
                slist[j+d]=slist[0];
            }
        }
        printf("第%d次排序结果:", count++);
        printList(slist, n);
    }
}
void quick_sort(int a[],int l,int r,int n) //快速排序
{
    int k=a[l];
    if(l<r)
    {
        int i=l,j=r;
        while(i<j)
        {
            while(a[j]>=k&&i<j) j--;
            a[i]=a[j];
            while(a[i]<=k&&i<j) i++;
            a[j]=a[i];
        }
        a[i]=k;
        printf("第%d次排序结果:", count++);
        printList(a,n);
        quick_sort(a,l,i-1,n);
        quick_sort(a,i+1,r,n);
    }
}
void BubbleSort(int list[],int n)  //冒泡排序
{
    int i,j,flag,temp;
    for(j=1; j<=n-1; j++)
    {
        flag=0;
        for(i=1; i<=n-j; i++)
        {
            if(list[i]>list[i+1])
                flag=1,temp=list[i],list[i]=list[i+1],list[i+1]=temp;

        }
        if(flag==0)
            break;
        printf("第%d次排序结果:", count++);
        printList(list,n);
    }
    return ;
}
void SelectSort(int a[],int n)   //选择排序
{
    int i,j,minn;
    int temp;
    for(i=1; i<n; i++)
    {
        minn=i;
        for(j=i+1; j<=n; j++)
            if(a[i]>a[j])
                minn=j;
        if(minn!=i)
            temp=a[i],a[i]=a[minn],a[minn]=temp;
        printf("第%d次排序结果:", count++);
        printList(a,n);
    }
    return ;
}
void Merge(int a[],int l,int r,int m,int n)
{
    int i=l,j=m+1,k=l;
    int temp[MAX];
    while(i<=m&&j<=r)
    {
        if(a[i]>a[j])
            temp[k++]=a[j++];
        else
            temp[k++]=a[i++];
    }
    while(i<=m)
        temp[k++]=a[i++];
    while(j<=r)
        temp[k++]=a[j++];
    for(i=l; i<=r; i++)
        a[i]=temp[i];
    printf("第%d次排序结果:", count++);
    printList(a,n);
}
void MergeSort(int a[],int l,int r,int n) //归并排序
{
    if(l<r)
    {
        int mid=(l+r)/2;
        MergeSort(a,l,mid,n);    //递归分成只有1个数的小区间
        MergeSort(a,mid+1,r,n);
        Merge(a,l,r,mid,n);
    }

}

/*生成待排序序列*/
void createList(int list[], int *n)
{
    int i = 1,a;
    printf("请输入待排序序列(长度小于50,以输入一个字符结束):\n");
    while(scanf("%d",&a)==1)
    {
        list[i] = a;
        i++;
    }
    *n=i-1;
    getchar();
}
/*输出排序结果*/
void printList(int list[], int n)
{
    int i = 1;
    for(; i <= n; i++)
    {
        printf("%d ", list[i]);
        if(i % 10 ==0 && i != 0)
            printf("\n");
    }
    printf("\n");
}

int main()
{

    int choice=1,length;
    while(choice!=0)
    {
        count=1;
        printf("\n");
        printf("***** 内部排序算法演示程序 *****\n");
        printf("\n1. 直接插入排序 \n");
        printf("\n2. 堆排序 \n");
        printf("\n3. 希尔排序 \n");
        printf("\n4. 快速排序 \n");
        printf("\n5. 冒泡排序 \n");
        printf("\n6. 选择排序 \n");
        printf("\n7. 归并排序 \n");
        printf("\n0. 退出\n");
        printf("\n请选择:");
        scanf("%d", &choice);
        getchar();
        switch(choice)
        {
        case 1:
        {
            createList(slist, &length);
            insertSort(slist, length);
            break;
        }
        case 2:
        {
            createList(slist, &length);
            heapSort(slist, length);
            break;
        }
        case 3:
        {
            createList(slist, &length);
            ShellSort(slist,length);
            break;
        }
        case 4:
        {
            createList(slist, &length);
            quick_sort(slist,1,length,length);
            break;
        }
        case 5:
        {
            createList(slist, &length);
            BubbleSort(slist, length);
            break;
        }
        case 6:
        {
            createList(slist, &length);
            SelectSort(slist, length);
            break;

        }
        case 7:
        {
            createList(slist, &length);
            MergeSort(slist,1,length,length);
            break;
        }

        default:
            choice=0;
        }
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值