各种排序算法的原理、实现及其时间复杂度

请你说一说你知道的排序算法及其复杂度 参考回答: 1、冒泡排序: 从数组中第一个数开始,依次遍历数组中的每一个数,通过相邻比较交换,每一轮循环下来 找出剩余未排序数的中的最大数并“冒泡”至数列的顶端。 稳定性:稳定 平均时间复杂度:O(n ^ 2) 2、插入排序: 从待排序的n个记录中的第二个记录开始,依次与前面的记录比较并寻找插入的位置,每次外 循环结束后,将当前的数插入到合适的位置。 稳定性:稳定 平均时间复杂度:O(n... 阅读详情

(1、冒泡排序  2、选择排序  3、插入排序  4、归并排序  5、快速排序  6、堆排序  7、希尔排序)


1、冒泡排序

原理:

  1.  比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2.  对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3.  针对所有的元素重复以上的步骤,除了最后一个。
  4.  持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
实现:
以数组{2,1,5,4,3}为例,实现过程如下图所示

代码:
public static void bubble(int [] a){
        for(int i=0;i<a.length-1;i++){
            for(int j=0;j<a.length-1-i;j++){
                if(a[j]>a[j+1]){
                    int temp=a[j];
                    a[j]=a[j+1];
                    a[j+1]=temp;
                }
            }
        }
    }
时间复杂度:若数组为正序,则一轮比较即可完成排序,时间复杂度为O(n)
若数组为逆序,则需要n-1轮起泡,每轮需要n-i-1次比较,时间复杂度为O(n^2)
2、选择排序
原理:在要排序的一组数中选出最小的数和第一个位置的数交换,在剩下的数中选择最下的和第二个位置的数交换,如此循环到最后一个数和倒数第二
个数比较。
实现:
仍以数组{2,1,5,4,3}为例,实现过程如下图所示

代码:
public static void select(int [] a){
        for (int i = 0; i < a.length; i++) {
            int min = a[i];
            int n=i;
            for(int j=i+1;j<a.length;j++){
                if(a[j]<min){
                    min = a[j];
                    n = j;
                }
            }
            a[n] = a[i];
            a[i] = min;
        }
    }
时间复杂度:O(n^2)
3、插入排序
原理:将第i个数与前i-1个数依次比较,如果有比i大的数则将i插入到这个数的前面。
实现:仍以数组{2,1,5,4,3}为例,实现过程如下图所示

代码:
public static void insert(int [] a){
        int temp=0 ;
        int j=0;
        for(int i=0;i<a.length;i++)
        {
            temp=a[i];
            //如果第i个数比前面的数小,就让前面的数向后移
            for(j=i;j>0&&temp<a[j-1];j --)
            {
                a[j]=a[j-1];
            }
            a[j]=temp;
        }
    }
时间复杂度:O(n^2)
以上是时间复杂度为O(n^2)的排序
下面介绍时间复杂度为O(nlogn)的排序
4、归并排序
原理:假设序列有n个元素,将此序列看成是n个长度为1的序列,将每两个相邻的序列进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素,将上述序列继续两两归并,形成floor(n/4)个序列排序,继续重复上一步,直至形成一个长度为n的序列。
实现:
以数组{3,5,4,2,1,8,9,7}为例,实现过程如下图所示

代码:
public static void sort(int[] data, int left, int right) {
        if (left < right){
            //找出中间索引
            int center = (left + right) / 2;
            //对左边数组进行递归
            sort(data, left, center); //递归时先调用的后返回,后调用的先返回,因此形参的值也跟随,根据栈的原则
            //对右边数组进行递归
            sort(data, center + 1, right); /*当center是0的时候,left=right,因此sort不再执行,继续*/

            //合并
            merge(data, left, center, right);
        }
    }

    public static void merge(int[] data, int left, int center, int right){
        int[] tmpArr = new int[data.length];
        int mid = center + 1;
        //third记录中间数组的索引
        int third = left;
        int tmp = left;
        while (left <= center && mid <= right){
            //从左右两个数组中取出小的放入中间数组,
            if (data[left]-data[mid]<= 0){
                tmpArr[third++] = data[left++];
            } else{
                tmpArr[third++] = data[mid++];
            }
        }
        //比较后剩余的其他数字部分依次放入中间数组
        while (mid <= right) {
            tmpArr[third++] = data[mid++];
        }
        while (left <= center) {
            tmpArr[third++] = data[left++];
        }
        //将中间数组中的内容复制拷回原数组
        //(原left~right范围的内容复制回原数组)
        while (tmp <= right){//已经排序好的数组

            data[tmp] = tmpArr[tmp++];
        }
        System.out.println("merge");
    }
5、快速排序
原理: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
实现:以数组{3,5,4,2,1,8,9,7}为例,实现过程如下图所示

代码:
public static void  quickSort(int[] data, int start, int end) { 
		int i = start;    //相当于i,左  索引
		int j = end;    //相当于j,  右  索引
		if (i >= j)  { // 判断是否到中间了 ,到中间返回
			return; //返回
		}
		//确定指针方向的逻辑变量,也就是从左搜索还是向右搜索 
		boolean flag=true; //false:左->右  true:右->左
		while (i != j) { //如果i==j证明第一趟结束,每趟的标准值仅是一个,例如第一趟被比较值为49,
			if (data[i] > data[j]) { 
				//交换数字 :所有比它小的数据元素一律放到左边,所有比他大的数据元素一律放到右边,
				int temp = data[i]; 
				data[i] = data[j]; 
				data[j] = temp; 
				//只有经过数的交换后,才能把游标的移动位置改变,移动书序是交替改变
				//决定下标移动,还是上标移动 ,游标更改 走下一个数据
				flag = (flag == true) ? false : true; 
			//	flag=!flag;
			} 
			//将指针向前或者向后移动 ,第一次从左-》右,第二次从右-》左
			if(flag) {//true,右---》左
				j--; 
			}else{//false 左---》右
				i++;
			}				 
		} 
		i--; 
		j++; 
		
		quickSort(data, start, i); 
		quickSort(data, j, end); 
	}
快排时间复杂度最优为O(nlogn),最差为O(n^2)
空间复杂度O(logn)~O(n)
6、堆排序
原理:先将待排序的数列构造成一个大顶堆(每个节点的值都比他的子节点的值大),此时序列的最大值就是堆顶的根节点,将其序列最后的元素交换,然后将剩下的n-1个数继续构造成一个大顶堆,则根节点为倒数第二的数,将其与序列倒数第二个位置的元素交换,如此反复最终得到一个正序序列。
实现:以数组{9,79,46,30,58,49}为例,实现过程如下图所示

代码:
public static void heapSort(int [] data) {
        System.out.println("开始排序");
        int arrayLength = data.length;
        //循环建堆
		/*
		 *        9
		 *      /   \
		 *    79    46
		 *   / \   /
		 * 30  58 49
		 */
        //针对完全二叉树,大顶堆,最顶端的值(0号索引)肯定是在没swap之前的最大的值,
        //对其在数组里面进行排序交换,大的排在数组后面,虽然最大的在最上面,但是其他的数据并没有排好,因此,需要不停更换顶点,重新建堆,需要循环
        for (int i = 0; i < arrayLength - 1 ; i++ ){//5 4 3 2 1
            //建堆
            builMaxdHeap(data, arrayLength - 1 -i);//-i的原因,就是数组中没经过一次循环,最大的数已经在数组的后面了,就不用在建堆了
            //由于是大顶锥方式:锥顶是最大的数,交换堆顶和最后一个元素
            System.out.print("交换锥顶前");
            System.out.println(Arrays.toString(data));

            swap(data, 0 , arrayLength - 1 - i);
            System.out.print("交换锥顶后");
            System.out.println(Arrays.toString(data));
        }
    }

    private static void builMaxdHeap(int [] data, int lastIndex){//修建大顶堆
        //从lastIndex处节点(最后一个节点)的父节点开始
        //(lastIndex - 1)/2    为最后一个节点的父节点的索引(除根节点)

        //都是从子节点开始判断  k的值分别是 5 3 1 索引号依次判断
		/*
		 *        9
		 *      /   \
		 *    79    46
		 *   / \   /
		 * 30  58 49
		 */
        for (int i = (lastIndex - 1) / 2 ; i >= 0  ; i--){//索引号从大的开始
            //k保存当前正在判断的节点
            int k = i;
            //如果当前k节点的子节点存在,
            //k * 2 + 1 判断当前节点的子节点
            while (k * 2 + 1 <= lastIndex){//看当前要判断k的子节点是否存在。
                //k节点的左子节点的索引
                int biggerIndex = 2 * k  + 1;
                //如果biggerIndex小于lastIndex,即biggerIndex + 1
                //代表k节点的右子节点存在
                if (biggerIndex < lastIndex){//防止溢出
                    //如果右子节点的值较大,biggerIndex存储的都是最大节点索引
                    if(data[biggerIndex]-(data[biggerIndex + 1]) < 0){//左面的小于右面的
                        //biggerIndex总是记录较大子节点的索引,之后再和父亲比
                        biggerIndex++; //这是较大节点的索引号,也就是右节点的索引号
                    }
                }
                //如果k(父节点)节点的值小于其较大子节点(左右都有可能)的值,交换
                if(data[k]-(data[biggerIndex]) < 0){
                    //交换它们
                    swap( data,k , biggerIndex);
                    //将biggerIndex赋给k,开始while循环的下一次循环,
                    //重新保证k节点的值大于其左、右子节点的值。
                    k = biggerIndex;//大节点的索引号,
                }else{//满足的条件刚好是节点的值大于子节点的值
                    break;//刚好进入下一层循环
                }
            }
        }
    }
    //交换data数组中i、j两个索引处的元素
    private static void swap(int [] data, int i , int j){
        int tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
    }
7、希尔排序
原理: 把记录按 步长  gap  分组,对每组记录采用 直接插入排序 方法进行排序。 随着 步长逐渐减小 ,所分成的组包含的记录越来越多,当步长的值减小到  1  时,整个数据合成为一组,构成一组有序记录,则完成排序。
实现:

代码:
public void shellSort(int[] list) {
        int gap = list.length / 2;
        while (1 <= gap) {
            // 把距离为 gap 的元素编为一个组,扫描所有组
            for (int i = gap; i < list.length; i++) {
                int j = 0;
                int temp = list[i];
                // 对距离为 gap 的元素组进行排序
                for (j = i - gap; j >= 0 && temp < list[j]; j = j - gap) {
                    list[j + gap] = list[j];
                }
                list[j + gap] = temp;
            }
            gap = gap / 2; // 减小增量
        }
    }

(希尔排序的文字描述、图片、代码均来自->  希尔排序 )














Python使用netmiko配置华为交换机 1.netmiko就是专门为网络设备做的模块,非常强大。1.更适合网络设备的自动化运维模块。2、批量配置变更、备份。1.安装netmiko。2. 创建SSH连接。一、netmiko介绍。 阅读详情

相关推荐

保姆级教程:用海思PQTool搞定ISP图像调试,从参数读取到固件烧录全流程

本文提供海思PQTool的ISP图像调试全流程指南,从参数读取、实时调试到固件烧录,涵盖环境配置、核心功能解析、参数固化及生产部署。通过实战案例和避坑指南,帮助开发者高效提升图像质量,适用于海思开发板的ISP调试与优化。

weixin_30872337的博客 282

常见排序算法及其对应的时间复杂度、空间复杂度

常见排序算法及其对应的时间复杂度、空间复杂度: 排序算法经过长时间演变,大体可以分为两类:内排序和外排序。在排序过程中,全部记录存放在内存,则成为内排序;如果排序过程中需要使用外存,则称为外排序,本文讲的都属于内排序。 内排序有可以分为以下几类: (1)插入排序:直接插入排序、二分法插入排序、希尔排序 (2)选择排序:直接选择排序、堆排序 (3)交换排序:冒泡排序、快速排序 (4)归并排序 (5)基数排序 一、插入排序 •思想:每步将一个待排序的...

YUBANGSHUANGYUER的博客 6797

如何从RHEL 8升级到RHEL 9

Red Hat 于 2022 年 5 月 17 日宣布全面推出 RHEL 9。这是 RHEL(Red Hat Enterprise Linux)的最新版本,它具有许多功能和增强功能。

u012748257的博客 1020

各个排序算法的时间复杂度、稳定性、快排的原理以及图解

一、整体介绍 常见的数据结构算法如下图所示: 常见数据结构算法的时间复杂度、空间复杂度、稳定性介绍如下图所示: 二、分部介绍: (1)直接插入排序: 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果新元素小于已排序元素tmp<array[ j ],将该元素移到下一位置array[ j+1]=array[ j ] 重复步骤3 j - -,直到找到已排序的元素小于或者等于新元素的位置 array[ j ]<=tmp.

1万+

python blp模型 估计_随机系数Logit模型及Stata实现

欢迎投稿(荐稿)计量经济圈,计量相关都行邮箱:econometrics666@sina.cn作者:北京交通大学经济管理学院博士生,王琦珀。欢迎你加入计量经济圈社群,一起探讨前沿计量理论和实证方法。一、随机系数Logit模型1.背景实证产业组织(Empirical Industrial Organization,EIO)是目前产业组织理论的前沿,其中又以Ariel Pakes为带头人,其近期工作论文...

weixin_42298927的博客 2641

(35)远程识别(又称无人机识别)(一)

Ardupilot官网关于《Peripheral Hardware》的翻译 —《(35) 远程识别(又称无人机识别)》。

无人机开发(开源Ardupilot) 4万+

常用排序算法

8种常用排序算法

南飞的孤雁 3639

Android 15.0 系统开机屏幕设置默认横屏显示

在15.0的系统ROM产品定制化开发中,对于产品需求来说,由于是宽屏设备所以产品需要开机默认横屏显示,开机横屏显示这就需要从 两部分来实现,一部分是系统开机动画横屏显示,另一部分是系统屏幕显示横屏显示,从这两方面就可以做到开机默认横屏显示了

安卓兼职framework和app工程师的博客 719

常见的排序算法 原理&时间复杂度&实现

一、冒泡排序 二、快速排序 三、选择排序 四、归并排序 排序思想很重要,分治的算法思想 五、堆排序 六、桶排序 七、所有排序算法总结

zhq0808的博客 544

阅文集团大数据面试题及参考答案

在 Flink 中,watermark 是一种用于处理乱序事件时间的机制。实现接口:通常需要实现 AssignerWithPeriodicWatermarks 或 AssignerWithPunctuatedWatermarks 接口。前者会周期性地生成 watermark,后者则是基于某些特定事件来生成 watermark ,比如接收到某个特定值的消息时。定义位置:可以在数据源处或者在流处理的中间操作中定义 watermark。在数据源定义时,能更精准地根据数据的产生特性设置 watermark;

大模型大数据攻城狮的专栏 1089

ROS & ROS2 机器人深度相机激光雷达多传感器标定工具箱

不过,多传感器标定工具箱允许通过编辑 yaml 文件来调整标定目标的参数: <repository>/mutlisensor_calibration/cfg/TargetWithCirclesAndAruco.yaml%YAML:1.0rows: 4cols: 1dt: irows: 4cols: 2dt: frows: 1cols: 12dt: fCAD 模型网格/云通过 GICP 将模型数据与分割点云对齐,用于优化检测到的目标姿态。

2506_90492529的博客 2109

[排序算法] 冒泡排序的原理及其Java实现

**冒泡排序**,其实现方式,是在每一轮操作中从头部开始把相对较大的数组后部移动,这途中如果遇到更大的元素,那就选择更大的元素向后移动。这样能保证每一轮移动都能让最大的元素“冒泡”到数组尾部。也正是因为这个特性,这个算法被命名为冒泡排序。

ToraNe的博客 358

TI Sitara系列AM64x开发板(双核ARM Cortex-A53)软硬件规格书

创龙科技TL64x-EVM是一款基于TI Sitara系列AM64x双核ARM Cortex-A53 + 单/四核Cortex-R5F + 单核Cortex-M4F多核处理器设计的高性能评估板,由核心板和评估底板组成。评估板接口资源丰富,引出5x Ethernet(两路支持TSN)、2x CAN-FD、多路UART、多路DI/DO、GPMC、PCIe、USB等接口,板载WIFI模块,支持4G/5G模块、NVME硬盘,可选配外壳直接应用于工业现场,方便用户快速进行产品方案评估与技术预研。

创龙,嵌入式一体化解决方案商 727

排序算法时间复杂度

复习排序算法

lf1593572468的博客 545

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

堆排序时间复杂度_十大经典排序算法——堆排序

堆排序总算把你给盼来了现在才关注我 确实是晚了点但没关系 来了就好工具:vs code 、ppt操作系统:LinuxSUMMER目录1.十大经典排序算法总结1.1、排序分类1.2、排序的定义1.3、术语说明1.4、算法总结1.5、图片名词解释1.6、比较类排序与非比较类排序的区别8.堆排序(HeapSort)8.1、说明 8...

weixin_39983383的博客 1304

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

【Java 数据结构】常见排序算法(上)

本期主要讲解: 1、 认识排序 2、常见排序的分类 3、直接插入排序 4、希尔排序(缩小增量排序) 5、选择排序 6、堆排序

程序猿教你打篮球的博客 4467

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

【排序算法】选择排序

选择排序

SWsunlight的博客 2626

java常用三种排序算法---(插入,冒泡,顺序)及其时间复杂度

java三种排序算法 1.插入排序 插入排序,稳定(改变一部分数组数值的位置)(时间最坏复杂度 O(n^2)最优均为O(n)) 插入排序的算法核心为把当前插入的位置之前变为有序 2.冒泡排序 冒泡排序,不稳定(会改变大部分部分数组数值的位置)(时间最坏复杂度 O(n^2)最优均为O(n)) 冒泡排序每次出来一个最值是其核心算法所在 3.选择排序 选择排序,不稳定(会改变大部

有才而性缓,定属大才。有智而气和,斯为大智。 2772

Python 实现选择排序算法

选择排序(selection sort): 选择排序算法如下: 首先在未排序序列中找到最小(大)元素, 存放到排序序列的起始位置 然后再从剩余未排序元素中继续寻找最小(大)元素,放到已排序列的末尾 以此类推 其时间复杂度: ​​​​​​​最优时间复杂度: O(n²) 最坏时间复杂度: O(n²) 选择排序稳定性: 不稳定( 考虑升序每次选择最大的情况 ) 代码实...

Nick.Peng's Blogs 1942

猴子排序算法

该定理内容大致为:给一只猴子一台打印机,虽然这只猴子根本不识字,但会乱按,经过一段时间后,在它乱按出来的单词里总能找到一些至少看起来是有意义的部分,比如一两个简短的单词,由此可以推出:只要给它足够长的时间,猴子甚至能完整地写出一本莎士比亚全集。千百年来,衔尾蛇被赋予了数不清的意义,其中就包括较易理解的“循环”,“无限”,以及偏向神学概念的“生死循环”与“轮回”,还有现代科学意义上的“熵增”,甚至惊天动地的“宇宙真理”。猴子算法的意义更多的是理论上的而非应用上,它打破了排序算法时间复杂度的极限,在。

qq_41757528的博客 4918

排序算法——比较类排序算法讲解以及c++实现

首先我先抛一个老哥的博客,我是看着他的博客来学习理解 地址:https://www.cnblogs.com/onepixel/p/7674659.html 首先说一下排序算法分为2类:一类是比较类排序算法,另一类是非比较类排序,这里主要讲常用的比较类排序算法 包括插入排序,选择排序,冒泡排序,希尔排序,快速排序,归并排序,堆排序 先讲一下各个算法的复杂度 时间复杂度方面,快速排序,归并排序,堆排序的是最好的,一般比较常用。 1.插入排序(时间复杂度o(n2)) 它的工作原理是通..

Demo.demo的博客 2047

python排序算法(一) 冒泡、选择

排序 排序算法(Sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法。 排序算法的稳定性 稳定排序算法会让原本有相等键值的记录维持相对次序。也就是如果一个排序算法是稳定的,当有两个相等键值的记录R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前。 当相等的元素是⽆法分辨的,⽐如像是整数,稳定性并不是⼀个问题。然⽽,假设以下的数对将要以他们的第...

阿鹏的博客 287

关于常用的排序算法

常用的排序算法 -排序算法- -平均时间复杂度- 冒泡排序 O(n2) 选择排序 O(n2) 插入排序 O(n2) 希尔排序 O(n1.5) 快速排序 O(N*logN) 归并排序 O(N*logN) 堆排序 O(N*logN) 基数排序 O(d(n+r)) 冒泡排序 所谓冒...

AndroidDeveloperHoly的博客 189

八大排序算法JAVA实现(时间复杂度O(n-logn)篇)

本文讲述时间复杂度为n*logn的排序算法:归并排序、快速排序、堆排序以及希尔排序的原理、Java实现以及变形应用。 一、归并排序  原理:把两个有序数列合并为一个有序数列。需递归实现。  Java实现: 1 public int[] mergeSort(int[] a, int n) 2 { 3 return doMergeSort(a,

wmz545546的博客 473

1. 排序算法基础

文章目录1. 排序算法的介绍1.2 排序的分类1.2.1 常见的排序算法分类1.3 算法的时间复杂度1.3.1 度量一个程序(算法)执行时间的两种方法1.3.2 时间频度基本介绍忽略常数项忽略低次项忽略系数1.3.3 时间复杂度计算时间复杂度的方法1.3.4 常见的时间复杂度常见的时间复杂度对应的图(可跳过)常数阶 O(1)对数阶 O(log2n)线性阶 O(n)线性对数阶 O(nlogN)平方阶 O(n²)立方阶 O(n³)、K 次方阶 O(n^k)1.3.5 平均时间复杂度和最坏时间复杂度1.4 算法的

weixin_45267102的博客 290

PHP实现排序算法总结

1、冒泡排序原理:两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。 时间复杂度:该算法的时间复杂度为O(n2)。但是,当原始关键字序列已有序时,只进行一趟比较就结束,此时时间复杂度为O(n)。function bubbleSort($array) { // 不是数组或者空数组,直接返回 if (!is_array($array) |

野蛮秘籍 553
上一篇: Java知识点小总结(一)
下一篇: 二叉树的实现及其遍历
yang_9613
博客等级 码龄10年 1粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值