排序算法(选择排序、直接插入排序、冒泡排序、二路归并排序)(C语言版)

对数组进行排序,主要演示选择排序、直接排序、冒泡排序、二路归并排序算法,附上代码演示

一、编写好各类排序方法的函数

(1) s_sort(int e[],int n):选择排序。

(2)si_sort(int e[],int n):直接插人排序。

(3)sb_sort(int e[],int n):冒泡排序。

(4)merge(int e[],intn);二路归并排序。

二、调用上述函数实现下列操作:

(1)给定数组 E[N]={213,111,222,77,400,300,987,1024,632,555};

(2)调用选择排序函数进行排序;

(3)调用直接插人函数进行排序;

(4)调用冒泡函数进行排序;

(5)调用二路归并排序函数进行排序。

三、代码演示:

1、选择排序源代码:

bash 复制代码
#include<stdio.h>
#include<conio.h>
#define N 10
int E[N] = { 213, 111, 222, 77, 400, 300, 987, 1024, 632, 555 };

void s_sort( int e[], int n )/* e:存储线性表的数组 n:线性表的结点个数 */
{
    int i, j, k, t;
    for( i = 0; i < n-1; i++ ) {    /* 控制n−1趟的选择步骤 */
        /* 在e[i], e[i+1],...,e[n−1]中选键值最小的结点e[k] */
        for( k = i, j = i + 1; j < n; j++ )
            if( e[k] > e[j] )
                k = j;
        if( k != i ) {      /* e[i]与e[k]交换 */
            t = e[i];
            e[i] = e[k];
            e[k] = t;
        }
    }
}

void main()
{
    int i;
    printf( "顺序排序  初始数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        s_sort( E, N );   
    printf( "\n排序后数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        getch();
}

2、直接插入排序源代码

bash 复制代码
#include<stdio.h>
#include<conio.h>
#define N 10
int E[N] = { 213, 111, 222, 77, 400, 300, 987, 1024, 632, 555 };

void si_sort( int e[], int n )  /* e:存储线性表的数组  n:线性表的结点个数 */
{
    int i, j, t;
    for( i = 1; i < n; i++ ){/* 控制e[i], e[i+1],...,e[n−1]的比较插入步骤 */
        /* 找结点e[i]的插入位置 */
        // t = e[i];
        for(t = e[i]; j >= 0 && t < e[i-1]; j--)
            
            e[j+1] = e[j];
            e[j+1] = t;
    }
}
  
void main()
{
    int i;
    printf( "直接排序  初始数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        si_sort( E, N );
    printf( "\n排序后数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        getch();
}

3、冒泡排序

bash 复制代码
#include<stdio.h>
#include<conio.h>
#define N 10
int E[N] = { 213, 111, 222, 77, 400, 300, 987, 1024, 632, 555 };

void sb_sort( int e[], int n )  /* e:存储线性表的数组  n:线性表的结点个数 */
{
    int j, p, h, t;
    for( h = n-1; h > 0; h = p ) {
        for( p = j = 0; j < h; j++ )
            if( e[j] > e[j+1] ) {
                t = e[j];
                e[j] = e[j+1];
                e[j+1] = t;
                p = count2;
            }
        }
}
       
void main()
{
    int i;
    printf( "冒泡排序,初始数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        sb_sort( E, N );   
    printf( "\n排序后数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        getch();
}

4、二路归并排序

bash 复制代码
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#define N 10
int E[N] = { 213, 111, 222, 77, 400, 300, 987, 1024, 632, 555 };

void merge_step( int e[], int a[], int s, int m, int n )    /* 两个相邻有序段的合并 */
{
    int i, j, k;
    k = i = s;
    j = m + 1;
    while( i <= m && j <= n )   /* 当两个有序都未结束时循环 */
        if( e[i] <= e[j] )          /* 取其中小的元素复制 */
            a[k++]=e[i++];
        else
            a[k++] = e[j++];
    while( i <= m )                 /* 复制还未合并完的剩余部分 */
        a[k++] = e[i++];
    while( j <= n )                 /* 复制还未合并完的剩余部分 */
            a[k++] = e[j++];
}
void merge_pass( int e[], int a[], int n, int len ) 
/* 完成一趟完整的合并 */
{
    int f_s, s_end;
    f_s = 0;
    while( f_s + len < n ) {    /* 至少有两个有序段 */
        s_end = f_s + 2 * len - 1;
        if( s_end >= n )            /* 最后一段可能不足len个结点 */
            s_end = n - 1;
        merge_step( e, a, f_s, f_s + len - 1, s_end );  /* 相邻有序段合并 */
        f_s = s_end + 1;            /* 下一对有序段中左段的开始下标为上一对末尾+1 */
    }
    if( f_s < n )                   /* 当还剩一个有序段时, 将其从e[]复制到a[] */
        for( ; f_s < n; f_s++ )
            a[f_s] = e[f_s];
}

void merge( int e[], int n )    /* 二路合并排序 */
{
    int *p, len=1, f=0;
    p = (int *)malloc( n * sizeof(int) );
    while( len < n ) {  /* 交替地在e[]和p[]之间来回合并 */
        if( f == 0 )
            merge_pass( e, p, n, len );
        else
            merge_pass( p, e, n, len );
            len*=2; /* 一趟合并后,有序结点数加倍 */
        f = 1 - f;      /* 控制交替合并 */
    }
    if( f == 1 )            /* 当经过奇数趟合并时,从p[]复制到e[] */
        for( f = 0; f < n; f++ )
            e[f] = p[f];
    free( p );
}

void main()
{
    int i;
    printf( "归并排序,初始数据序列为:\n" );
    for( i = 000; i < N; i++ )
        printf( "%d ", E[i] );
        merge( E, N );    
    printf( "\n排序后数据序列为:\n" );
    for( i = 0; i < N; i++ )
        printf( "%d ", E[i] );
        getch();
}

四、运行结果:

1、选择排序的运行结果:

2、直接插入排序

3、冒泡排序

4、二路归并排序

五、总结:

1、插入排序:按关键字大小插入到前面已经排好序的子序列中;直接插入排序是稳定的排序,空间复杂度是O(1);最好的情况时间复杂度为O(n),最坏的时间复杂度为O(n²);

2、冒泡排序:时间复杂度T(n)=O(n²);空间复杂度S(n)=O(1);

3、选择排序:每次从当前待排序的记录中选取关键字最小的记录表,然后与待排序的记录序列中的第一个记录进行交换,直到整个记录序列有序为止。简单选择排序:时间复杂度是T(n)=O(n²),空间复杂度是S(n)=O(1);是不稳定的;

4、归并排序:时间复杂度为O(m+n);2-路归并排序,两两归并排序使其有序;时间复杂度无论最好还是最坏都是O(nlog₂n);空间复杂度是O(n);归并排序是稳定的;

相关推荐
想跑步的小弱鸡4 小时前
Leetcode hot 100(day 3)
算法·leetcode·职场和发展
xyliiiiiL5 小时前
ZGC初步了解
java·jvm·算法
爱的叹息6 小时前
RedisTemplate 的 6 个可配置序列化器属性对比
算法·哈希算法
独好紫罗兰6 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法
每次的天空7 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
请来次降维打击!!!7 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
qystca7 小时前
蓝桥云客 刷题统计
算法·模拟
别NULL7 小时前
机试题——统计最少媒体包发送源个数
c++·算法·媒体
weisian1518 小时前
Java常用工具算法-3--加密算法2--非对称加密算法(RSA常用,ECC,DSA)
java·开发语言·算法
程序员黄同学9 小时前
贪心算法,其优缺点是什么?
算法·贪心算法