冒牌排序(BubbleSort)

冒泡排序是一种比较简单的排序算法,它循环走过需要排序的元素,依次比较相邻的两个元素,如果顺序错误就交换,直至没有元素交换,完成排序。

若对n个人进行排序,我们需要n-1次比较,所以第k次比较需要进行n-k次比较。排序算法通过以数据对象的两两比较作为关键,所以可以得出,冒泡排序需要进行的

比较次数为:(n-1) + (n-2) + ... + 1 = n*(n-1) / 2,因此冒泡排序的时间复杂度为O(n^2)。

算法简介:

       1.比较相邻的元素,前一个比后一个大(或者前一个比后一个小)调换位置

       2.每一对相邻的元素进行重复的工作,从开始对一直到结尾对,这步完成后,结尾为做大或最小的数.

       3.针对除了最后一个元素重复进行上面的步骤。

       4.重复1-3步骤直到完成排序

动画演示:

 

 代码如下

#include<stdio.h>
void BuddleSort(int a[],int n){
    
    for(int i=0;i<n-1;i++){
        for( int j=0;j<n-i-1;j++){
            if(a[j]>a[j+1]){
                int swap=a[j];
                a[j]=a[j+1];
                a[j+1]=swap;
            }
        }
    }
}
int main(){
    int a[]={6, 9,8,4,5,2,1,3,7};
    int n=sizeof(a)/sizeof(int);
    BuddleSort(a,n);
    printf("冒泡排序结果:");
    
    for (int i = 0; i < n; i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
}

冒牌排序改进版:鸡尾酒排序

鸡尾酒排序:又名为定向冒泡排序,相比较于传统的冒泡排序改进方法就是加入一个标志性变量exchange,用于标志某次排序过程中

是否由数据交换,若某一次排序没有进行数据交换,则说明数据已经排列好,可以立刻结束排序,避免不必要的后续比较过程,从而提高性能。

算法描述:每次排序进行正向和反向冒泡一次得到两个终值(最大值和最小值)。

代码如下

#include<stdio.h>
void BuddleSort(int a[],int n)
{
    int left=0;   //设置变量初始值
    int right=n-1;
    int swap,j;
    while(left<right){
        for(j=left;j<right;j++)//正向冒泡,找出最大值
        {
            if(a[j]>a[j+1])
            {
                swap=a[j];
                a[j]=a[j+1];
                a[j+1]=swap;
            }
        }
            right--; //前移一位
        for(int j=right;j>left;j--)//反向冒泡找出最小值
        {
            if(a[j-1]>a[j])
            {
                swap=a[j];
                a[j]=a[j-1];
                a[j-1]=swap;
            }
        }
        left++; //修改left值。后移一位
    }
}
int main()
{
    int a[]={7,8,4,2,9,5,6,1,3};
    int n=sizeof(a)/sizeof(int);
    BuddleSort(a,n);
     printf("鸡尾酒排序结果:");
    for (int i = 0; i < n; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
 }

 选择排序(SelectSort)

选择排序是一种简单直观的排序算法,工作原理为:在未排序的序列中找出最小(大)元素与第一个位置的元素交换位置

注意选择排序与冒泡排序的区别:冒泡排序通过依次交换相邻两个顺序不合法的元素位置,从而将当前最小(大)元素放到合适的位置;而选择排序每遍历一次都记住了当前最小(大)元素的位置,最后仅需一次交换操作即可将其放到合适的位置。

然后在剩下的元素中再找最小(大)元素与第二个元素的位置交换,依此类推,直到所有元素排序排序完成。根据上述描述,一共进行n-1趟比较后,就能完成整个排队过程。我们可以知道,第k趟比较需要进行的数组元素的两两比较的次数为n-k次,所以共需要的比较次数为n*(n-1) / 2,因此选择排序算法的时间复杂度与冒泡排序一样,也为O(n^2)。

算法简介:

     1.初始状态:序列为无序状态。

     2.第1次排序:从n个元素中找出最小(大)元素与第1个记录交换

     3.第2次排序:从n-1个元素中找出最小(大)元素与第2个记录交换

     4.第i次排序:从n-i+1个元素中找出最小(大)元素与第i个记录交换

    5.以此类推直到排序完成

动画演示:

代码如下

#include<stdio.h>
void SelectSort(int a[],int n)
{
    for(int i=0;i<n-1;i++)
    {
        int min=i;  //存放数组最小值的位置
        
        for(int j=i+1;j<n;j++)
        {
            if(a[j]<a[min]){
                min=j;   //找出最小值,并记录位置
            }
         }
         if(min!=i) //最小元素与第i个元素互换位置
         {
            int swap=a[min];
             a[min]=a[i];
             a[i]=swap;
         }
    }
}
int main()
{
    int a[]={8,9,7,1,5,4,2,3,6};
    int n=sizeof(a)/sizeof(int);
    SelectSort(a,n);
     printf("选择排序结果:");
    for (int i = 0; i < n; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

 插入排序(InsertSort)

插入排序是一种简单直观的排序算法,工作原理为构建有序序列,对于未排序元素,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间,直到排序完成,如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。理解了插入排序的思想后,我们便能够得到它的时间复杂度。对于n个元素,一共需要进行n-1轮比较,而第k轮比较需要进行k次数组元素的两两比较,因此共需要进行的比较次数为:1 + 2 + ... + (n-1),所以插入排序的时间复杂度同冒泡排序一样,也为O(n^2)。

算法简介:

     1.从第一个元素开始,该元素可认为已排序。

     2.取出下一个元素,在排序好的元素序列中从后往前扫描

     3.如果元素(已排序)大于新元素,将该元素移到下一位置

     4.重复3.直到找到已排序的元素小于或等于新元素的位置

     5.将新元素插入该位置后

     6.重复2-5直到排序完成

动画演示:

代码如下

#include<stdio.h>
void InsertSort(int a[],int n)
{
    for(int i=0;i<n;i++)
    {
        int j=i-1;
        if(a[i]<a[i-1]){ //若第i个元素小于第i-1个元素,移动有序序列插入------大于的话则直接插入
        int swap=a[i];  //存储将要排序的元素
        a[i]=a[i-1];   //向后移动一个元素
        while(swap<a[j])//查询将要插入的位置
        {
            a[j+1]=a[j];
            j--;       //元素后移
        }
        a[j+1]=swap;//循环结束 插入到指定位置
    }    
    }
}
int main() {
    int a[] = { 9,7,8,2,5,1,3,6,4};
    int n = sizeof(a)/sizeof(int);
    InsertSort(a, n);
    printf("排序好的数组为:");
    for (int i = 0; i < n; i++) {
        printf(" %d", a[i]);
    }
    printf("\n");
    return 0;
}

还有几种经典的排序算法没有写出,后续将补充,有不足之处还请指出。谢谢

排序算法(Gif动图演示)的更多相关文章

  1. 转发自:一像素 十大经典排序算法(动图演示)原链接:https://www.cnblogs.com/onepixel/articles/7674659.html 个人收藏所用 侵删

    原链接:https://www.cnblogs.com/onepixel/articles/7674659.html     个人收藏所用   侵删 0.算法概述 0.1 算法分类 十种常见排序算法可 ...

  2. 八大排序算法详解(动图演示 思路分析 实例代码java 复杂度分析 适用场景)

    一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...

  3. 八大排序算法——希尔(shell)排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序:随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止. 简单插 ...

  4. 八大排序算法——插入排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 例如从小到大排序: 1.  从第二位开始遍历, 2.  当前数(第一趟是第二位数)与前面的数依次比较,如果前面的数大于当前数,则将这个数放在当前数的位置上,当前数的下标-1 ...

  5. 八大排序算法——堆排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 先来了解下堆的相关概念:堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆:或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆.如 ...

  6. 八大排序算法——归并排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序 1.  向上归并排序的时候,需要一个暂存数组用来排序, 2.  将 ...

  7. 八大排序算法——快速排序(动图演示 思路分析 实例代码Java 复杂度分析)

    一.动图演示 二.思路分析 快速排序的思想就是,选一个数作为基数(这里我选的是第一个数),大于这个基数的放到右边,小于这个基数的放到左边,等于这个基数的数可以放到左边或右边,看自己习惯,这里我是放到了 ...

  8. 八大排序算法——冒泡排序(动图演示 思路分析 实例代码java 复杂度分析)

    一.动图演示 二.思路分析 1.  相邻两个数两两相比,n[i]跟n[j+1]比,如果n[i]>n[j+1],则将连个数进行交换, 2.  j++, 重复以上步骤,第一趟结束后,最大数就会被确定 ...

  9. 八大排序算法——选择排序(动图演示 思路分析 实例代码Java 复杂度分析)

    一.动图演示 二.思路分析 1.  第一个跟后面的所有数相比,如果小于(或小于)第一个数的时候,暂存较小数的下标,第一趟结束后,将第一个数,与暂存的那个最小数进行交换,第一个数就是最小(或最大的数) ...

  10. JS十种经典排序算法,纯动画演示,学会了怼死面试官!

    十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间非比较类排序:不通过比较来决定 ...

随机推荐

  1. vue中直接修改props中的值并未给出警告,为啥?

    问:vue中直接修改props中的值并未给出警告,为啥? 答:如果props传入的值是引用类型,在子组件中改变其元素,不改变引用,那么不报错: 如果是基本类型,那么在修改时浏览器控制台会有报错信息. ...

  2. SQL :“传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确” 错误

    其中在DAL层调用存储过程来插入数据的参数 SqlParameter[] parameters = {                                            new S ...

  3. 工控随笔_20_西门子_WinCC的VBS脚本_09_常量和流程控制_02

    vbs不但提供了分支结构,还提供了丰富的循环形式.一共有3种循环: 1.for循环 2.do...loop循环 3.while循环 各种循环有各自的特点,在使用的时候可以进行转换. 前面已经描述过Fo ...

  4. JavaScript 对象属性底层原理

    对象属性类型 1. 数据属性 [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,特性默认值为true [[Enum ...

  5. Mvc 提交表单的4种方法

     一,MVC  HtmlHelper方法 1.     Html.BeginForm(actionName,controllerName,method,htmlAttributes){} 2.     ...

  6. [原创] JAVA 递归线程池测试 ExecutorService / ForkJoinPool

    测试工具使用递归的方式获取子进程的Msg消息,目前有2种常用的ExecutorService / ForkJoinPool 为了测试哪种效果较好,我们来写个测试Demo,循环5555555次+1(加锁 ...

  7. [蓝桥杯]PREV-22.历届试题_国王的烦恼

    问题描述 C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在多座桥连接.然而,由于海水冲刷,有一些大桥面临着不能使用的危险. 如果两个小岛间 ...

  8. mysql循环插入千万级数据

    mysql使用存储过程循环插入大量数据,简单的一条条循环插入,效率会很低,需要考虑批量插入. 测试准备: 1.建表: CREATE TABLE `mysql_genarate` ( `id` ) NO ...

  9. 好玩的PIL

    原图(下面的代码全为部分)不喜欢的一个库 缩小的代码 from PIL import Image im=Image.open('tupian.jpg') im.thumbnail(128,128)) ...

  10. Servlet-Context学习笔记

    介绍 ServletContext其实就是全局作用域对象, 上下文环境对象 利用context可以实现对,当前网站中所有的Servlet共享数据 context对象只能由Tomcat负责创建,在tom ...