C语言实现经典排序算法的示例代码

目录
  • 一、冒泡排序
    • 1.原理
    • 2.实现
    • 3.算法分析
  • 二、选择排序
    • 1.原理
    • 2.实现
    • 3.算法分析
  • 三、插入排序
    • 1.原理
    • 2.实现
    • 3.算法分析
  • 四、希尔排序
    • 1.原理
    • 2.实现
    • 3.算法分析
  • 总结

一、冒泡排序

1.原理

从数组的头开始不断比较相邻两个数的大小,不断将较大的数右移,一个循环后,最大数移至最后一位,无序数组规模减一。不断重复前面动作,知道数组完全有序。

2.实现

void swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
void bubble_sort(int* arr, int len)
{
    bool issort = false;
    while (!issort)
    {
        issort = true;//如果有序则直接退出
        for (int i = 1; i < len; i++)
        {
            if (arr[i-1] > arr[i])//不断比较相邻两个数
            {
                swap(&arr[i - 1], &arr[i]);//将较大的数不断往右移
                issort = false;//如果进行了交换则无序
            }
        }
        len--;//无序规模减一
    }
}

3.算法分析

时间复杂度: 最好情况,当数组完全有序,则只需要进行一轮比较,时间复杂度为o(n);最坏情况为完全无序,每次比较后都要将该数移至数组末尾,时间复杂度为o(n ^2);平均时间复杂度为o(n ^2)。

空间复杂度: 冒泡排序为就地排序,空间复杂度为o(1)。

稳定排序: 当数字相同时不会改变相对次序。

二、选择排序

1.原理

数组前面为无序,后面为有序。刚开始全是无序,从中选择一个最大值与最后一个无序数字进行交换,无序数组规模减一,有序数组规模加一。不断循环前面操作,直到数组变为有序数组。或者前面为有序数组,后面为无序数组,不断选择最小值与无序数组的第一个数交换,前面的有序数组加一,后面的无序数组减一。

2.实现

void selection_sort(int* arr, int len)
{
    int max_index;
    while (len)
    {
        max_index = 0;
        for (int i = 1; i < len; i++)
        {
            if (arr[max_index] < arr[i])
            {
                max_index = i;//获取最大值的索引
            }
        }
        swap(&arr[max_index], &arr[len - 1]);//将最大值与最后一个值交换
        len--;//无序规模减一
    }
}

3.算法分析

时间复杂度: 所有的复杂度为每次选择最大值,不管数字的有序性,时间复杂度都为o(n)+o(n-1)+…+o(1)=o(n^2)。所以该算法平均复杂度、最好情况、最差情况都为o(n ^2)。

空间复杂度: 就地排序,空间复杂度为o(1)。

不稳定性算法: 排序后相同元素的顺序可能被打乱。例子:选择最大进行排序。3,1,2,2* 第一轮排序后 2*,1,2,3 2的相对顺序发生了改变。选择最小进行排序,2*,2,3,1 第一轮排序后1,2,3,2*. 2的相对顺序也被打乱。如果增加空间复杂度也能将选择排序变成稳定性排序。

三、插入排序

1.原理

数组前面为有序,后面为无序,将无序数组中的第一个数不断插入有序数组中(具体实现为不断比较相邻两数大小,前面一个数大于后一个数,则交换顺序,较小的数不断前移),有序规模增加一,无序规模减小一。或者,数组前面为无序,后面为有序,通过将无序数组的最后一位数字插入有序数组中(具体实现为将无序数组的最后一位与相邻的有序数组不断比较,将无序数组不断右移)。

2.实现

void insert_sort(int arr[], int len)
{
    for (int i = 1; i < len; i++)//i前面为有序
    {
        for (int j = i - 1; j >= 0; j--)//j为有序数的末尾
        {
            bool issort = true;//当数组有序时能够提前退出
            if (arr[j] > arr[j + 1])//将无序数组的第一个数不断与有序数组比较
            {
                swap(&arr[j], &arr[j + 1]);//将无序数字插入有序数组合适的位置
                issort = false;
            }
            if (issort) break;
        }
    }
}

3.算法分析

时间复杂度: 插入排序和冒泡排序类似,最好情况完全有序则时间复杂度为o(n),最坏情况为完全无序时间复杂度为o(n^2),平均复杂度为o(n ^2)。

空间复杂度: 就地排序不需要额外空间,空间复杂度为o(1)。

稳定性排序: 和冒泡排序类似。

四、希尔排序

1.原理

每次选择一个增量进行分组,增量不断减小到一(为插入排序),数组不断变得有序,增量为一时变成完全有序。属于插入排序的改进,通过增量进行分组,对每一组进行插入排序,相比于插入排序的优势在于,shell排序能够大尺度的移动每一组的最小值,而插入排序得挨着进行比较,所以shell排序效率更高。

增量为6:

每一组只有两个数,分别比较两个数的大小,如64,57交换顺序变成57,64,所有的分组比较完后继续缩减增量。

增量为3:

每一组有四个数,总共三组,分别为23,12,53,79;57,9,64,87;24,16,71,97;以增量开始(12开始)遍历数组,遍历到12则在第一组中对12进行插入排序,交换23和12的顺序;遍历到9则在第二组对9进行插入排序。。。。遍历到64对一组中的9,57,64进行插入排序。最后每一组都变得有序。整体有序性变大。

增量为1:

对之前排序过的数组进行插入排序,通过前面的步骤数组有序性变大,最后进行插入排序的效率就更高。

2.实现

void shell_sort(int* arr, int len)
{
    int gap = 0; //分组的跨度
    int i = 0;
    int j = 0;
    for (gap = len / 2; gap >= 1; gap /= 2) //分组增量
    {
        for (i = gap; i < len; i++) {  //遍历每组
            for (j = i - gap; j >= 0; j -= gap)  //对组内进行插入排序
            {
                if (arr[j] > arr[j + gap])
                {
                    swap(&arr[j], &arr[j + gap]);
                }
            }
        }
    }
}

3.算法分析

时间复杂度:最好情况为完全有序o(n),最差情况为完全无序o(n^2),平均复杂度为o(n ^1.3)。

空间复杂度:该算法为就地排序空间复杂度为o(1)。

稳定性:shell排序在分组中可能将相同数字划分成不同的分组,会改变相对顺序,属于不稳定性排序算法。

总结

冒泡排序、选择排序、插入排序、希尔排序的实现都是基于线性表进行实现的(数组或者链表),实现逻辑都是通过比较数字的大小。算法的时间复杂度都比较大,但是属于就地排序,不需要额外空间。几种算法相比之下希尔排序更具有优势。

到此这篇关于C语言实现经典排序算法的示例代码的文章就介绍到这了,更多相关C语言排序算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言实现冒泡排序算法的示例详解

    目录 1. 问题描述 2. 问题分析 3. 算法设计 动图演示 4. 程序设计 设计一 设计二 结论 5. 流程框架 6. 代码实现 7. 问题拓展 1. 问题描述 对N个整数(数据由键盘输入)进行升序排列. 2. 问题分析 对于N个数因其类型相同,我们可利用 数组 进行存储. 冒泡排序是在 两个相邻元素之间进行比较交换的过程将一个无序表变成有序表. 冒泡排序的思想:首先,从表头开始往后扫描数组,在扫描过程中逐对比较相邻两个元素的大小. 若相邻两个元素中,前面的元素大于后面的元素,则将它们互换,

  • C语言完整实现12种排序算法(小结)

    目录 1.冒泡排序 2.插入排序 3.折半插入排序 4.希尔排序 5.选择排序 6.鸡尾酒排序 7.堆排序 8.快速排序 9.归并排序 10.计数排序 11.桶排序 12.基数排序 1.冒泡排序 思路:比较相邻的两个数字,如果前一个数字大,那么就交换两个数字,直到有序.时间复杂度O(n^2),稳定性:这是一种稳定的算法.代码实现: void bubble_sort(int arr[],size_t len){ size_t i,j; for(i=0;i<len;i++){ bool hasSwa

  • C语言实现交换排序算法(冒泡,快速排序)的示例代码

    目录 前言 一.冒泡排序 1.基本思想 2.优化 3.扩展 二.快速排序 1.基本思想 2.优化 3.代码 前言 查找和排序是数据结构与算法中不可或缺的一环,是前辈们在算法道路上留下的重要且方便的一些技巧,学习这些经典的查找和排序也能让我们更好和更快的解决问题.在这个专栏中我们会学习六大查找和十大排序的算法与思想,而本篇将详细讲解其中的交换排序——冒泡排序和快速排序: 注意:本文中所有排序按照升序排序,降序只需要把逻辑反过来即可! 一.冒泡排序 1.基本思想 对于很多同学来说冒泡排序是再熟悉不过

  • C语言常见排序算法之插入排序(直接插入排序,希尔排序)

    目录 前言 一.直接插入排序 1.1 基本思想 1.2 算法思想 1.3 程序实现 1.4 直接插入排序的总结 二.希尔排序 2.1 算法思想 2.2 程序实现 2.3 希尔排序的特征总结 前言 本期为大家带来的是常见排序算法中的插入排序,主要有直接插入排序以及它的升级版——希尔排序,包您一看就会,快来试试吧~ 一.直接插入排序 1.1 基本思想 在生活当中,这种排序方式处处可见: 在玩扑克牌的时候我们就会采用插入排序的思想,当我们拿起第二张牌时,就会下意识的与第一张牌进行比较,如果比第一张牌小

  • C语言直接插入排序算法

    目录 1.算法模板 2.算法介绍 3.实例 总结 1.算法模板 void InsertSort(SqList *L) { int j; for (int i = 2; i <= L->length; i ++ ) { if (L->arr[i] < L->arr[i-1]) { L->arr[0] = L->arr[i]; // 设置哨兵 for (j = i - 1; L->arr[j] > L->arr[0]; j -- ) L->ar

  • C语言实现各种排序算法实例代码(选择,冒泡,插入,归并,希尔,快排,堆排序,计数)

    目录 前言 选择排序 冒泡排序 插入排序 归并排序 希尔排序 快速排序 堆排序 计数排序 总结 前言 平时用惯了高级语言高级工具高级算法,难免对一些基础算法感到生疏.但最基础的排序算法中实则蕴含着相当丰富的优化思维,熟练运用可起到举一反三之功效. 选择排序 选择排序几乎是最无脑的一种排序算法,通过遍历一次数组,选出其中最大(小)的值放在新数组的第一位:再从数组中剩下的数里选出最大(小)的,放到第二位,依次类推. 算法步骤 设数组有n个元素,{ a 0 , a 1 , - , a n } 从数组第

  • C语言实现经典排序算法的示例代码

    目录 一.冒泡排序 1.原理 2.实现 3.算法分析 二.选择排序 1.原理 2.实现 3.算法分析 三.插入排序 1.原理 2.实现 3.算法分析 四.希尔排序 1.原理 2.实现 3.算法分析 总结 一.冒泡排序 1.原理 从数组的头开始不断比较相邻两个数的大小,不断将较大的数右移,一个循环后,最大数移至最后一位,无序数组规模减一.不断重复前面动作,知道数组完全有序. 2.实现 void swap(int* a, int* b) { int temp = *a; *a = *b; *b =

  • python实现经典排序算法的示例代码

    以下排序算法最终结果都默认为升序排列,实现简单,没有考虑特殊情况,实现仅表达了算法的基本思想. 冒泡排序 内层循环中相邻的元素被依次比较,内层循环第一次结束后会将最大的元素移到序列最右边,第二次结束后会将次大的元素移到最大元素的左边,每次内层循环结束都会将一个元素排好序. def bubble_sort(arr): length = len(arr) for i in range(length): for j in range(length - i - 1): if arr[j] > arr[j

  • Go语言实现常用排序算法的示例代码

    目录 冒泡排序 快速排序 选择排序 插入排序 排序算法是在生活中随处可见,也是算法基础,因为其实现代码较短,应用较常见.所以在面试中经常会问到排序算法及其相关的问题,可以说是每个程序员都必须得掌握的了.为了方便大家学习,花了一天的时间用Go语言实现一下常用的算法且整理了一下,如有需要可以参考. 冒泡排序 思路:从前往后对相邻的两个元素依次进行比较,让较大的数往下沉,较小的网上冒,即每当两个相邻的元素比较后发现他们的排序要求相反时,就将它们互换. 时间复杂度:O(N^2) 空间复杂度:O(1) f

  • Java实现8种排序算法的示例代码

    冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次数,也是冒泡的结果位置下标,5个数组循环5次 for (int i = 0; i < a.length; i++) { //从最后向前面两两对比,j是比较中下标大的值 for (int j = a.length - 1; j > i; j--) { //让小的数字排在前面 if (a[j] <

  • C语言实现可排序通讯录的示例代码

    目录 1.目的 2.分部流程 1.初始化通讯录 2.添加联系人 3.判断联系人是否存在 4.判断通讯录是否已满 5.判断通讯录是否为空 6.通讯录扩容 7.核心函数 8.查找联系人 9.修改联系人 10.清空通讯录 11.删除联系人 12.显示通讯录 13.比较联系人 14.通讯录排序 3.总代码展示 1.目的 写一个实用型通讯录,它有如下功能: 显示目录 void ShowMenu() { printf("#######################\n"); printf(&qu

  • Golang实现常见排序算法的示例代码

    目录 前言 五种基础排序算法对比 1.冒泡排序 2.选择排序 3.插入排序 4.快速排序 前言 现在的面试真的是越来越卷了,算法已经成为了面试过程中必不可少的一个环节,你如果想进稍微好一点的公司,「算法是必不可少的一个环节」.那么如何学习算法呢?很多同学的第一反应肯定是去letcode上刷题,首先我并不反对刷题的方式,但是对于一个没有专门学习过算法的同学来说,刷题大部分是没什么思路的,花一个多小时暴力破解一道题意义也不大,事后看看别人比较好的解法大概率也记不住,所以我觉得「专门针对算法进行一些简

  • PHP实现常见排序算法的示例代码

    目录 1.冒泡排序 2.选择排序 3.快速排序 4.插入排序 补充 1.冒泡排序 两两相比,每循环一轮就不用再比较最后一个元素了,因为最后一个元素已经是最大或者最小. function maopaoSort ($list) { $len = count($list); for ($i = 0; $i < $len - 1; $i++) { for ($j = 0; $j < $len - $i - 1; $j++) { if ($list[$j] > $list[$j + 1]) { $

  • Java实现基本排序算法的示例代码

    目录 1. 概述 2. 插入排序 2.1 直接插入排序 2.2 希尔排序(缩小增量排序) 3. 选择排序 3.1 直接选择排序 3.2 堆排序 4. 交换排序 4.1 冒泡排序 4.2 快速排序 5. 归并排序 6. 计数排序(非比较类型的排序) 7. 排序算法总结 1. 概述 排序概念:就是将一串记录按照其中某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性:通俗的将就是数据元素不发生有间隔的交换,例如: 内部排序:数据元素全部放在内存中的排序 外部排序:数据元素太多不能一次加载到内

  • Java实现拓扑排序算法的示例代码

    目录 拓扑排序原理 1.点睛 2.拓扑排序 3.算法步骤 4.图解 拓扑排序算法实现 1.拓扑图 2.实现代码 3.测试 拓扑排序原理 1.点睛 一个无环的有向图被称为有向无环图.有向无环图是描述一个工程.计划.生产.系统等流程的有效工具.一个大工程可分为若干子工程(活动),活动之间通常有一定的约束,例如先做什么活动,有什么活动完成后才可以开始下一个活动. 用节点表示活动,用弧表示活动之间的优先关系的有向图,被称为 AOV 网. 在 AOV 网中,若从节点 i 到节点 j 存在一条有向路径,则称

  • Java实现常见的排序算法的示例代码

    目录 一.优化后的冒泡排序 二.选择排序 三.插入排序 四.希尔排序 五.快速排序 六.随机化快速排序 七.归并排序 八.可处理负数的基数排序 一.优化后的冒泡排序 package com.yzh.sort; /* 冒泡排序 */ @SuppressWarnings({"all"}) public class BubbleSort { public static void BubbleSort(int[]a){ for (int i = 0; i <a.length-1 ; i+

随机推荐