基本排序算法

十大基本排序算法的简易可视化 本文利用Microsoft Visual Studio的C语言编写平台及其自带的输出窗口尝试制作了十种基本排序算法的简单可视化。最终的输出都是文字、数字与符号,笔者已经尽力调整其位置以让结果尽可能清楚。本来是自己在学习排序算法的时候希望可以看到输入的数据在计算机内部被操作的过程,这样方便理解,同时又想用尽可能简单(懒)的方式实现,所以做了这些尝试。相比于网上的动画式可视化工具,本方法在视觉效果上略逊一筹。 阅读详情

冒泡排序

基本思想:两两相邻进行比较,将最大的放到后面,每轮比较都会使需要比较的元素数目减一,总共需要比较length-1轮。由于嵌套for循环,时间复杂度最优和平均都是o(n^2),空间复杂度o(1)。冒泡排序是稳定的。

public class Main {

    public static void bubblingSort(int[] list) {
        int i, j;
        int length = list.length;
        for (i = length - 1; i > 0; i--) {
            for (j = 0; j < i; j++) {
                if (list[j] > list[j + 1])
                    swap(list, j, j + 1);
            }
        }
    }

    /**
     * 打印
     * @param list
     */
    private static void show(int[] list) {
        for (int i : list) {
            System.out.print(i + " ");
        }
        System.out.println();
    }


    /**
     * 交换
     * @param list
     * @param a
     * @param b
     */
    public static void swap(int[] list, int a, int b) {
        int temp = list[a];
        list[a] = list[b];
        list[b] = temp;
    }

    public static void main(String[] args) {
        int[] list = new int[] { 2, 17, 5, 1, 2, 8, 4, 13, 11, 6 };
        bubblingSort(list);
        show(list);
    }

}

优化点:如果数组为[3,2,4,5],其实在执行第一轮后,[2,3,4,5],数组已经有序,为了避免数组有序情况下继续执行循环,可以设定一个信号flag,改进代码如下

public static void bubblingSort(int[] list) {
    int i, j;
    int length = list.length;
    boolean flag=true;//设定信号量,初始化为true
    for (i = length - 1; i > 0&&flag; i--) {
        flag=false;//每一轮都将信号量置为flase
        for (j = 0; j < i; j++) {
            if (list[j] > list[j + 1]){
                swap(list, j, j + 1);
                flag=true;//该轮发生交换,继续执行下一轮;否则数组已经有序,跳出循环
            }
        }
    }
}

选择排序

基本思想:每轮选出最小的元素与每轮第一个元素交换
{5,4,1,3} -> {1,4,5,3} -> {1,3,5,4} -> {1,3,4,5}
平均、最好、最坏的时间复杂度都是o(n^2),空间复杂度o(1)。选择排序不是稳定的如{5,5,2}。

public static void choiceSort(int[] list) {
    int i, j;
    int length = list.length;
    int temp;//记录每一轮最小值
    int index;//记录每一轮最小值下标
    for(i=0;i<length-1;i++){
        temp=list[i];
        index=i;
        for(j=i+1;j<length;j++){
            if(list[j]<temp){
                //更新最小值
                temp=list[j];
                index=j;
            }
        }
        //将最小值与该轮的第一个元素交换
        swap(list,i,index);
    }
}

插入排序

基本思想:玩扑克牌,每次抓取一张牌,都将它插入到手牌合适的位置。
原数组:{5,4,1,3}
排序:{5} -> {4,5} -> {1,4,5} -> {1,3,4,5}
最好情况时间复杂度:o(n),如{1,2,3,4},只需要遍历(n-1)次。平均、最坏均是o(n^2)。空间复杂度:o(1)。插入排序是稳定的。

public static void insertSort(int[] list) {
    int i, j;
    int length = list.length;
    int temp;//记录抽取卡牌的值
    //从第二张牌开始插入
    for(i=1;i<length;i++){
        temp=list[i];
        //将抽取的牌与手牌逐一比较,找到合适位置,大于抽取卡牌值的手牌需要向后移一步
        for(j=i;j>0&&temp<list[j-1];j--){
            list[j]=list[j-1];
        }
        list[j]=temp;//插入合适位置
    }
}

希尔排序

基本思想:其实希尔排序是插入排序的一种优化,插入排序中提及到,当所需要排序的数组是有序的(默认为升序)情况下,达到最优时间复杂度。希尔排序就是借助这个特性进行优化,设置一个增量值gap,先粗略地对数组进行插入排序,通过不断缩小gap的值,继续对数组进行细化排序,由于每次都是基于前一次排序的结果进行插入排序,使得比较次数减小。借用dreamcatcher-cx博主的图:
这里写图片描述

public static void shellSort(int[] list) {
    int i, j;
    int length = list.length;
    int temp;//插入的卡牌
    int gap;//增量值
    for(gap=length/2;gap>0;gap/=2){
        for(i=gap;i<length;i++){
            //流程和插入排序差不多
            temp=list[i];
            //注意循环出口j-gap>=0,否则在判断temp<list[j-gap]会报数组越界错误
            for(j=i;j-gap>=0&&temp<list[j-gap];j-=gap){
                list[j]=list[j-gap];
            }
            list[j]=temp;
        }
    }
}

值得注意的是,希尔排序并不像直接插入排序,它是不稳定的,例如{4,3,3,2},当gap=2,排序得:{3,2,4,3};当gap=1,排序得{2,3,3,4}。另外,希尔排序的平均时间复杂度也是不确定的o(nlogn)~o(n^2),最好情况o(n^1.3),最坏情况o(n^2)。空间复杂度o(1)。


快速排序

基本思想:【坐在马桶上看算法】算法3:最常用的排序——快速排序
时间复杂度:平均o(nlogn),最优o(nlogn),最坏o(n^2)如{4,3,2,1}
空间复杂度:o(logn)~o(n),主要因为使用递归会占用栈空间
稳定性:不稳定

public static void sort(int[] list,int left,int right) {
if(left>=right) return;//递归出口
    //找到中点
    int mid=execute(list,left,right);
    //左右分支
    sort(list,left,mid-1);
    sort(list,mid+1,right);
}

public static int execute(int[] list,int left,int right){
    int base=list[left];//设置基数,这里取最左元素,会可能导致出现最坏情况,后续优化
    int index=left;//记录基数下标
    while(left<right){
        //右指针向左移动,找到比基数值小的元素(为什么右指针先行?)
        while(left<right){
            if(list[right]<base) break;
            right--;
        }
        //左指针向右移动,找到比基数大的元素
        while(left<right){
            if(list[left]>base) break;
            left++;
        }
        if(left<right){
            swap(list,left,right);//左右指针值交换
        }
    }
    swap(list,index,left);//基数与中间值交换
    return left;//返回中间值下标
}

这里有两个问题,首先解决为什么右指针先移动,我们假设现在处于这种情况:
quick1
选取5为基数
quick2
如果左指针先行,找到7>5
quick3
然后右指针向左移动,right==left,跳出循环,执行swap(list,index,left)。
quick4
将基数和中间值交换后,发现基数5的左边明显不是所有数都小于5,排序出现错误。

那么第二个问题,为什么选取最左或者最右元素作为基数会可能导致最坏情况出现?继续举个栗子:
快排的基本步骤

if(left>=right) return;//递归出口
//找到中点
int mid=execute(list,left,right);
//右分支
sort(list,mid+1,right);
//左分支
sort(list,left,mid-1);

假设初始数组{4,3,2,1}

这里写图片描述
第一次mid返回3,进入右分支sort(list,4,3)left>right退出递归,进入左分支sort(list,0,2)

这里写图片描述
第二次mid返回0,进入右分支sort(list,1,2),进入左分支sort(list,0,-1)left < right退出递归

这里写图片描述
第三次mid返回2,进入右分支sort(list,3,2)退出递归,进入左分支sort(list,1,1)退出递归。第三次结束后数组排序完成,观察发现,总共执行n-1次。由于每次调用递归,栈深度加一,可以得出空间复杂度o(n),而每次左指针需要遍历到最右边或者右指针需要遍历到最左边,所以时间复杂度为o(n^2)。对于进一步的优化,可参考快速排序及优化(Java实现)


归并排序

基本思想:递归分治,对数组不断地对半拆分,然后再重新排序合并,如图(图片来源)
这里写图片描述
时间复杂度:平均、最好、最坏都是o(nlogn)。
空间复杂度:o(n),借助临时数组。
稳定性:稳定。

public static void mergeSort(int[] list,int left,int right) {
    if(left>=right) return;//递归出口
    //找到中点
    int mid=(left+right)/2;
    //左右分支
    mergeSort(list,left,mid);
    mergeSort(list,mid+1,right);
    //归并
    execute(list,mid,left,right );
}

public static void execute(int[] list,int mid,int left,int right){
    //临时数组
    int[] temp=new int[right-left+1];
    int i=left,j=mid+1;
    int k=0;
    while(i<=mid&&j<=right){
        //左右两边比较,较小的先放入数组
        if(list[i]<list[j]){
            temp[k++]=list[i++];
        }else{
            temp[k++]=list[j++];
        }
    }
    //将剩余的放入temp
    while(i<=mid) temp[k++]=list[i++];
    while(j<=right) temp[k++]=list[j++];
    //将临时数组值放入list
    for(int t=0;t<temp.length;t++){
        //注意放入list的起始下标应该从left开始
        list[left+t]=temp[t];
    }
}

堆排序

基本思想:构建一个堆, 使得根节点值最大,将根节点与堆最后一个元素交换,重新构建堆,堆大小减一,反复执行。
时间复杂度:o(nlogn)。
空间复杂度:o(1)。
稳定性:不稳定。

public static void heapSort(int[] list) {
    //建堆,从最后一个父节点开始,由下至上构建堆
    for(int i=list.length/2-1;i>=0;i--){
        adjust(list,list.length,i);
    }
    //排序
    for(int i=list.length-1;i>0;i--){
        //堆顶和数组最后一个元素交换
        swap(list,0,i);
        //调整堆
        adjust(list,i,0);
    }
}

/**
 * 构建或者调整堆
 * @param list
 * @param size 堆大小
 * @param i 当前父节点
 */
public static void adjust(int[] list,int size,int i){
    //左右节点
    int left=i*2+1;
    int right=i*2+2;
    //记录左右节点最小值下标
    int maxindex=i;
    if(left<size&&list[left]>list[maxindex]) maxindex=left;
    if(right<size&&list[right]>list[maxindex]) maxindex=right;
    //minIndex未发生改变,即当前父节点最小,返回
    if(maxindex==i) return;
    //交换父子节点,重新构建堆
    swap(list,i,maxindex);
    adjust(list,size,maxindex);
}
十种基本排序算法 十种基本排序算法 代码自己慢慢找哈 #define _CRT_SECURE_NO_WARNINGS #include<Windows.h> #include<stdio.h> #define MaxSize 10//归并排序,桶排序等排序时需要申请和原数组一样大小的空间时用到,方便修改 //快排 int QuickShortchild(int *str, int lef... 阅读详情

相关推荐

龙虾 Skill 技能库|OpenClaw+Hermes 全集成 一键调用所有 AI 技能

龙虾 Skill 技能库、OpenClaw、Hermes Agent、AI 技能集成、本地 AI 自动化、办公工具、数字员工

weixin_42219287的博客 624

搞懂基本排序算法

搞懂基本排序算法 上篇文章写了关于 Java 内部类的基本知识,感兴趣的朋友可以去看一下:搞懂 JAVA 内部类;本文写的内容是最近学习的算法相关知识中的基本排序算法,排序算法也算是面试中的常客了,实际上也是算法中最基本的知识。由于 Android 开发中用到的地方并不多,所以也很容易遗忘,但是为了进阶高级工程师巩固基本算法和数据结构也是必修课程之一。 基本排序算法按难易程度来说可以分...

王小六的博客 786

第零章 序 Chisel教程汇总

笔者目前西安交通大学微电子硕士在读,研究方向为数字集成电路设计与体系结构。鉴于目前RISC-V的火热程度,笔者参与了课题组的RISC-V项目,并了解、学习了颇受关注的新型硬件构建语言——Chisel,当前参与的神经网络加速器设计便是使用Chisel开发的。这是一门敏捷开发语言,据称要比传统的Verilog语言快很多。在亲身使用过后,笔者发现确实快了不少。这主要得益于Scala作为高级语言的简洁风格...

qq_34291505的博客 7万+

基本排序算法总结

排序算法总结冒泡排序选择排序插入排序归并排序快速排序希尔排序基数排序计数排序桶排序Tim排序 冒泡排序 冒泡算法是基于比较的排序算法,排序思想:当前元素比下一个元素大(或小)的时候,就与之进行交换。 void BubbleSort(vector<int> &nums) { for(int i=0;i<nums.size()-1;i++) { for(int j=0;j<nums.size()-i-1;j++) { if(nums[j]>nums[j+1

weixin_42168958的博客 223

通俗傻瓜式理清光栅化渲染和光线追踪渲染的原理

用通俗语言傻瓜式的讲清楚光栅渲染和光线追踪渲染的原理,方便没有相关理论基础的朋友理解入门。

qq_37366618的博客 2万+

【Python LeetCode 专题】面试经典 150 题

面试经典 150 题

一杯水果茶!足矣~ 1172

基本排序算法小结

一、插入排序 1  排序思想     将待排序的记录Ri,插入到已排好序的记录表R1, R2 ,…., Ri-1中,得到一个新的、记录数增加1的有序表。 直到所有的记录都插入完为止。复杂度为O(n2) 。     设待排序的记录顺序存放在数组R[1…n]中,在排序的某一时刻,将记录序列分成两部分: ◆ R[1…i-1]:已排好序的有序部分; ◆ R[i…n]:未排好序的无序部分。

肖氏专栏 2157

基于模糊神经网络实现水质评价预测 - Matlab源码

首先定义输入层、隐含层和输出层的节点数,并初始化权重和阈值,然后开始训练模型,在每轮训练中通过比较模型的输出值与实际值的误差来更新权重和阈值,直到误差达到最小值,为了提高模型的性能,我们可以采用交叉验证等技术进行优化。首先需要准备好数据集,使用的是嘉陵江的水质监测数据集,数据集包含了多个指标,如 pH 值、溶解氧、总氮、总磷等,以及相应的水质等级,我们需要将数据集分为训练集和测试集。在当今环境日益恶化的情况下,水质监测变得越来越重要,模糊神经网络作为一种新型的。

weixin_50547796的博客 147

基本的排序算法

基本的排序算法 Java实现各种基本的排序算法 冒泡排序 冒泡排序:这种排序方法是通过相邻的两个元素两两比较,根据大小来交换位置,最值元素就像气泡一样从左侧向右侧移动,故名冒泡排序。 public class BubbleSort { public static void main(String[] args) { int []a= {9,3,1,4,6,8,7,5,2}; sort(a); print(a); } //冒泡排序 static void sort(int[] a)

weixin_43731014的博客 303

升级conda时出现Malformed version string invalid chars错误解决方案

但有时,当你使用“conda upgrade”的命令时,你可能会遇到一个错误,提示你的环境解析失败,出现“Malformed version string invalid chars”错误消息。如果以上两个步骤都没有解决你的问题,那么你可以考虑更新conda的依赖项。如果你的conda版本已经是最新的,那么你需要清理conda的缓存。最后,如果以上方法都无法解决问题,你可以尝试使用pip进行更新。如果你的conda版本过旧,你需要先更新conda。首先,你需要确认你当前使用的conda版本。

BUG?不存在的! 1409

0基础学习diffusion_model扩散模型【易理解的公式推导】Denoising Diffusion Probabilistic Models

去噪扩散概率模型。本文是笔者在学习扩散模型时的一些笔记与心得,在公式推导过程中能够保证自己是一步一步去推导并且理解了的。概述是我认为比较重要的部分能够帮助理解公式的推导,具体的公式推导在每一小节中进行。1、扩散过程:如上图所示,扩散过程为从右到左X0→XTX0​→XT​的过程,表示对图片逐渐加噪,且Xt1X_{t+1}Xt1​是在XtX_{t}Xt​加躁得到的,其只受XtX_{t}Xt​的影响,因此扩散过程是一个马尔科夫过程。X0X_0。

zik的博客 2397

三个基本排序算法

1选择排序 1.1过程分析 对于一个不确定的整形数组,首先将i=0所在的数和后面的所有数进行比较,找出最小的数i=j交换数组中的数,下一次再从i=1开始比较,直到i=num.length-1 1.2动画分析 1.2算法描述 public class selectsort { public static void main(String[] args) { int[] num= {2,3,5,4,1,9,8,7};//要排序的数组 T1(num); for(int n:num) //增强型f

正在自我救赎的菜鸟。本人所有内容均不收费,可随意转发,复制 1192

使用podspec创建iOS插件

概述 在WWDC 2014全球开发者大会上,苹果开放了动态库、App Extension等全新的功能,这为iOS插件化开发带来了可能。在iOS开发中,动态库是iOS提供的一种资源打包方式,可以将代码文件、头文件、资源文件和说明文档等集中在一起,并且可以在运行时进行动态加载。 目前,很多应用越做越复杂,应用程序也显得越来越臃肿。试想一下,如果将一些不常用的功能做成一个插件,然后根据用户的需求从网络中...

xiangzhihong8的专栏 991

PHP基本排序算法

基本排序算法 bubblesort 冒泡排序 insertsort 插入排序 shellsort 希尔排序 selectsort 简单查找排序 quicksort 快速排序 &lt;?php /* * bubble的原理:数组的前两个数字对比 * 每次数字大的后移一位 * 如果数字的长度是10 需要最多排序9次 */ function bubbleSort(array $numbe...

Aspire 200

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

排序算法之基本几种排序方法

排序算法 什么是排序算法 基本都排序算法有哪些 怎么衡量排序算法的优劣 冒泡排序的思想与c语言代码 插入排序的思想与c语言代码 1.什么是排序算法。 当你有一堆数据的时候,看着他们杂乱无章,无序的时候是不是看着特别不爽。是不是特想看着它们是从小到大,或者从大到小排列的,看着就舒服多了。还有哦,排序可不止是让你看着舒服,还有一部分是查找。在一堆数据中查找是否存在一个数据,如果是一堆杂乱无章的数据,我们就只能一个个比较,是否是你要的那个数据,...

m0_57614828的博客 2089

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

前端基本排序算法总结

前言 hellow大家好久不见,原本定于上周发的算法文章也因为电脑报废没有发送成功,这周刚好入手新电脑就着手发送文章了。 好了废话不多说,进入这次的主题基本排序算法,首先呢先说明一下虽然排序算法不是面试时必问的题目不过也可以排在前10的位置,另外呢我们日常会经常用到排序算法,我会举一些例子进行说明,就这样下面开始今天的讲解吧。 内容 冒泡排序 ...

weixin_30733003的博客 500

三种基本排序算法

三种基本排序排序算法 1.冒泡排序 基本原理: {3,5,4,2,6,1} 比较前两个元素{【3,5】,4,2,6,1} 3&amp;lt;5 保持不变 {3,[5,4],2,6,1} {3,4,[5,2],6,1} {3,4,2,[5,6],1} {3,4,2,5,[6,1]} {3,4,2,5,1,6} 第一遍排序完成,进行下一次排序,依次类推 由于最后一个元素已经是最大的...

weixin_42481455的博客 532

排序算法基本思想

 转自:http://yijiaotest.rdedu.net/yijiaotest/web/200552432039930/app/readnews.asp?id=8一、插入排序(Insertion Sort)1. 基本思想:  每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。2. 排序过程: 【示例】:[初始关键字] [

Day day up! 1524

四大基本排序算法实例

PHP四大基本排序算法包括:冒泡排序法,快速排序法,选择排序法,插入排序法。   1.冒泡排序   思路分析:在要排序的一组数中,对当前还未排好的序列,从前往后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即,每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。   代码实现: $arr=array(1,43,54,62,21,66,32,...

Again yy 407
上一篇: Volatile,Synchronized,Lock
下一篇: MySQL中拼接SQL语句
HamalAlpha
博客等级 码龄11年 5粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值