第八章 排序

news2024/9/29 7:22:17
一、插入排序
  1. 不带哨兵
void InsertSort(int A[], int n){
	int i, j, temp;
	for (i=1; i<n; i++){
		if (A[i]<A[i-1]){
			temp = A[i];
			for (j=i-1; j>=0 && A[j]>temp; --j){
				A[j+1] = A[j];
			}
			A[j+1] = temp;
		}
	}
}
  1. 带哨兵
void InsertSort(int A[], int n){
	int i, j;
	for (i=2; i<=n; i++){
		if (A[i]<A[i-1]){
			A[0] = A[i];
			for (j=i-1; A[0]<A[j]; --j){ // 不用每次循环都判断j>=0
				A[j+1] = A[j];
			}
			A[j+1] = A[0];
		}
	}
}

请添加图片描述

  1. 折半插入排序
    void InsertSort(ing A[], int n){
    	int i, j, low, high, mid;
    	for (i=2; i<=n; i++){
    		A[0] = A[i];
    		low = 1;
    		high = i-1;
    		while (low<=high){
    			mid = (high+low)/2;
    			if (A[mid]>A[0])
    				high = mid - 1;
    			else low = mid + 1;
    		}
    		for (j=i-1; j>=high+1; --j){
    			A[j+1] = A[j];
    		}
    		A[high+1] = A[0];
    	}
    }
    
二、 希尔排序

思想:先追求表中元素部分有序,再逐渐逼近全局有序
这里的A[0]只是暂存单元,不是哨兵(循环语句中会判断若j<=0就到了插入位置)

void ShellSort(int A[], int n){
	int d, i, j;
	for (d=n/2; d>=1; d=d/2)
		for (i=d+1; i<=n; ++i)
			if (A[i]<A[i-d]{
				A[0] = A[i];
				for (j=i-d; j>0 && A[0]<A[j]; i-=d)
					A[j+d] = A[j]; // 同组的记录后移,找寻当前元素的插入位置
				A[j+d] = A[0];
			}
}
三、冒泡排序

每一趟都能使最小的元素被放在最终位置(也可以改动以下代码使每一趟把最大的元素被放在最终位置)

void swap(int &a, int &b){
	int temp = a;
	a = b;
	b = temp;
}

void BubbleSort(int A[], int n){
	for (int i=0; i<n-1; i++){
		bool flag = false;
		for (int j=n-1; j>i; j--)
			if (A[j-1]>A[j]){
				swap(A[j-1], A[j]);
				flag = true;
			}
		if (flag==false)
			return;
	}
}
四、快速排序
void QuickSort(int A[], int low, int high){
	if (low<high){
		int pivotpos = Partition(A, low, high);
		QuickSort(A, low, pivotpos-1);
		QuickSort(A, pivotpos+1, high);
	}
}

int Partition(int A[], int low, int high){
	int pivot = A[low];
	while (low<high){
		while (low<high&&A[high]>=pivot) --high;
		A[low] = A[high];
		while (low<high&&A[low]<=pivot) ++low;
		A[high] = A[low];
	}
	A[low] = pivot;
	return low;
}
五、简单选择排序(属于选择排序)

每一趟在待排序元素中选取关键字最小的元素加入有序子序列(即有序子序列放在整个序列的开头,每一趟找到的最小元素放在有序子序列的末尾)

void SelectSort(int A[], int n){
	for (int i=0; i<n-1; i++){
		int min = i;
		for (int j=i+1; i<n; j++){
			if (A[j]<A[min])
				min = j;
		}
		if (min!=i)
			swap(A[i], A[min]);
	}
}

void swap(int &a, int &b){
	int temp = a;
	a = b;
	b = temp;
}		
六、堆排序(属于选择排序)

先建堆,再排序。建堆时让编号 ≤ n 2 \le\frac{n}{2} 2n的所有节点依次下坠(自底向上调整各分支节点),下坠规则就是小元素与关键字更大的孩子交换位置。排序时让堆顶元素加入有序子序列(大根堆排序时是让堆顶元素与堆底元素交换),堆底元素换到堆顶后,进行下坠调整,恢复大根堆的特性。将排序过程重复n-1趟

  1. 大根堆
    • 建立大根堆(A[0]初始值为空)
      void BuildMaxHeap(int A[], int len){
      	for (int i=len/2; i>0; i--) // 从后向前调整所有非终端节点 
      		HeadAdjust(A, i, len);
      }
      
      // 将以k为根的子树调整为大根堆(即小元素下坠过程)
      void HeadAdjust(int A[], int k, int len){
      	A[0] = A[k];  // A[0]的作用为暂存子树根节点(即要下坠的那个小元素)
      	for (int i=2*k; i<=len; i*2){  // 让i先指向当前节点左孩子
      		if (i<len && A[i]<A[i+1])
      			i++;
      		if (A[0]>=A[i]) break;
      		else{
      			A[k] = A[i];
      			k = i;
      		}
      	}
      	A[k] = A[0];
      }
      

      这里有个常考考点:若一个节点有两个孩子,则其“下坠”一层,需要对比关键字两次(孩子对比选最大,该节点再与大孩子对比);若下方只有一个孩子,则“下坠”一层只需对比关键字1次

    • 基于建立的大根堆,进行堆排序:每一趟将堆顶元素加入有序子序列(即有序子序列放在整个序列的结尾,每一趟找到的最大元素放在有序子序列的开头),并将待排序元素再次调整为大根堆(又进行一轮小元素不断下坠)
      void HeapSort(int A[], int len){
      	BuildMaxHeap(A, len);
      	for (int i=len; i>1; i--){
      		swap(A[i], A[1];
      		HeadAdjust(A, 1, i-1);
      	}
      }
      
七、归并排序

归并即把两个或多个已经有序的序列合并成一个

int *B = (int *)malloc(n*sizeof(int)); // 辅助数组B

void Merge(int A[], int low, int mid, int high){
	int i, j, k;
	for (k=low; k<=high; k++)
		B[k] = A[k]; // 将A中所有元素复制到B中
	for (i=low, j=mid+1, k=i; i<=mid&&j<=high; k++){
		if (B[i]<=B[j])
			A[k] = B[i++];
		else
			A[k] = B[j++];
	}
	while (i<=mid) 
		A[k++] = B[i++];
	while (j<=high)
		A[k++] = B[j++];
}

void MergeSort(int A[], int low, int high){
	if (low<high){
		int mid = (low+high)/2;
		MergeSort(A, low, mid);  // 对左半部分归并排序
		MergeSort(A, mid+1, high);  // 对右半部分归并排序
		Merge(A, low, mid, high);  // 归并
	}
}
八、基数排序

基数排序不是基于比较的排序算法
只考手动模拟,几乎不考代码

  1. 基数排序擅长解决的问题
    • 数据元素的关键字可以方便地拆分为d组,且d较小
    • 每组关键字的取值范围不大,即r较小
    • 数据元素个数n较大
  2. 基数排序通常基于链式存储实现:
    • 定义包含r个队列元素的数组,每个队列保存两个指针(*front和*rear),每个队列中的元素包含数据和指向下一个元素的指针
      typedef struct LinkNode{
      	ElemType data;
      	struct LinkNode *next;
      } LinkNode, *LinkList;
      
      typedef struct{
      	LinkNode *front, *rear;
      } LinkQueue;
      

请添加图片描述

九、外部排序
  1. 败者树:
    • 解决的问题:使用多路平衡归并可减少归并趟数,但用老土方法从k个归并段选出一个最小/最大元素需要对比关键字k-1次,构造败者树可以使关键字对比次数减少到 ⌈ l o g 2 k ⌉ \lceil log_2k \rceil log2k
    • 败者树可视为一棵完全二叉树(多了一个头头)。k个叶节点分别对应k个归并段中当前参加比较的元素,非叶子节点用来记忆左右子树中的“失败者”,而让胜者往上继续进行比较,一直到根节点
  2. 置换-选择排序:

算法效率

算法空间复杂度时间复杂度算法稳定性适用性
插入排序 O ( 1 ) O(1) O(1)最好 O ( n ) O(n) O(n);最坏 O ( n 2 ) O(n^2) O(n2);平均 O ( n 2 ) O(n^2) O(n2) (主要来自对比关键字、移动元素,若有n个元素,需要n-1趟处理)稳定
折半插入排序 O ( 1 ) O(1) O(1)最好 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n);最坏 O ( n 2 ) O(n^2) O(n2);平均 O ( n 2 ) O(n^2) O(n2)稳定
希尔排序 O ( 1 ) O(1) O(1)最坏 O ( n 2 ) O(n^2) O(n2)不稳定仅适用于顺序表,不适用于链表
冒泡排序 O ( 1 ) O(1) O(1)最好 O ( n ) O(n) O(n)(有序);最坏 O ( n 2 ) O(n^2) O(n2)(逆序);平均 O ( n 2 ) O(n^2) O(n2)稳定适用于顺序表和链表
快速排序最好 O ( l o g 2 n ) O(log_2n) O(log2n);最坏 O ( n ) O(n) O(n)最好 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)(每次选的pivot都能将序列分成均匀的两部分);最坏 O ( n 2 ) O(n^2) O(n2)(初始有序或逆序);平均 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)不稳定适用于顺序表,不适用于链表
简单选择排序 O ( 1 ) O(1) O(1) O ( n 2 ) O(n^2) O(n2)不稳定顺序表、链表都可以
堆排序 O ( 1 ) O(1) O(1)建堆 O ( n ) O(n) O(n)、排序 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n),总时间复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)不稳定
归并排序 O ( 1 ) O(1) O(1)每一趟的对比次数 O ( n ) O(n) O(n)、趟数 O ( l o g 2 n ) O(log_2n) O(log2n),总时间复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)稳定
基数排序 O ( r ) O(r) O(r) O ( d ( n + r ) ) O(d(n+r)) O(d(n+r)),其中数据元素的关键字拆分为d组,每组关键字的取值范围为r,数据元素个数为n稳定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1025758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序 实现滑块是矩形的slider组件

我发现大多数前端UI库都是圆形的滑块&#xff0c;而且圆形的滑块都没有紧贴进度条&#xff0c;都是超出了首尾端&#xff0c;所以亲自写一个矩形的滑块&#xff0c;我使用了微信小程序的wxs的事件通信写法&#xff0c;官方说这样写好&#xff0c;也不知道好哪里了。样式如下图&…

AWS入列CNCF基金会

7月27日&#xff0c;IT之家曾经报道&#xff0c;微软加入Linux旗下CNCF基金会&#xff0c;在这之后不到一个月的今天&#xff0c;亚马逊AWS也宣布&#xff0c;以铂金身份加入此基金会。 CNCF&#xff0c;全称Cloud Native Computing Fundation&#xff0c;该基金会旨在使得容器…

Java中Hashset存储原理底层深挖

上课老师讲了Hashset的添加元素方法&#xff0c;感觉不甚准确&#xff0c;于是下课扒一扒底层源码&#xff0c;这一看&#xff0c;霍&#xff01; 原来如此。现在小丁来捋一遍他的存储原理。 public boolean add(E e) {return map.put(e, PRESENT)null;} 可以看到PRESENT是一…

HTTPS 证书生成脚本详细讲解

前言 HTTPS证书的作用是用于保障网站的安全性。在HTTPS协议中&#xff0c;通过使用证书来实现客户端与服务器之间的认证和数据加密&#xff0c;防止中间人攻击、信息泄漏等安全问题的发生。https证书也就是SSL证书&#xff0c;我们首先要确定好需要 https 安全连接的域名&…

IMX6ULL移植篇-Linux内核源码目录分析一

一. Linux内核源码目录 之前文章对 Linux内核源码的文件做了大体的了解&#xff0c;如下&#xff1a; IMX6ULL移植篇-Linux内核源码文件表_凌肖战的博客-CSDN博客 本文具体说明 Linux内核源码的一些重要文件含义。 二. Linux内核源码中重要文件分析 1. arch 目录 这个目录…

Spring的后处理器

Spring后处理器 Spring后处理器是Spring对外开放的重要拓展点&#xff08;让我们可以用添加自己的逻辑&#xff09;&#xff0c;允许我们介入到Bean的整个实例化流程中来&#xff0c;以达到动态注册BeanDefinition&#xff08;向BeanDefitionMap中添加BeanDefition对象的过程&…

【视觉SLAM入门】8. 回环检测,词袋模型,字典,感知,召回,机器学习

"见人细过 掩匿盖覆” 1. 意义2. 做法2.1 词袋模型和字典2.1.2 感知偏差和感知变异2.1.2 词袋2.1.3 字典 2.2 匹配(相似度)计算 3. 提升 前言&#xff1a; 前端提取数据&#xff0c;后端优化数据&#xff0c;但误差会累计&#xff0c;需要回环检测构建全局一致的地图&…

数据结构与算法(C语言版)P5---栈

1、栈 1.1、栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。__进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。__栈中的数据元素遵守__后进先出&#xff08;先进后出&#xff09;__LIFO&#xf…

【C++STL基础入门】list改、查操作

文章目录 前言一、list查操作1.1 迭代器循环1.2 for_each函数 二、list改操作2.1 迭代器修改2.2 assign函数2.3 运算符 总结 前言 C标准模板库&#xff08;STL&#xff09;是C语言中非常重要的部分&#xff0c;它提供了一组通用的模板类和函数&#xff0c;用于处理常见的数据结…

利用C++开发一个迷你的英文单词录入和测试小程序-源码

接上一篇&#xff0c;有了数据库的查询&#xff0c;再把小测试的功能给补足&#xff0c;小程序的结构就出来了。 备注&#xff1a;enable_if 有更优秀的concept C 20替代品&#xff0c;C11 里面提到的any&#xff0c;variant&#xff0c;再C17 已经被纳入了标准库。这里完全可…

iOS加固保护技术:保护你的iOS应用免受恶意篡改

目录 转载&#xff1a;开始使用ipaguard 前言 下载ipa代码混淆保护工具 获取ipaguard登录码 代码混淆 文件混淆 IPA重签名与安装测试 转载&#xff1a;开始使用ipaguard 前言 iOS加固保护是直接针对ios ipa二进制文件的保护技术&#xff0c;可以对iOS APP中的可执行文件…

机器学习(17)---支持向量机(SVM)

支持向量机 一、概述1.1 介绍1.2 工作原理1.3 三层理解 二、sklearn.svm.SVC2.1 查看数据集2.2 contour函数2.3 画决策边界&#xff1a;制作网格2.4 建模画图 三、非线性情况推广3.1 查看数据集3.2 线性画图3.3 为非线性数据增加维度并绘制3D图像 四、核函数 一、概述 1.1 介绍…

记一次 mysql 数据库定时备份

环境&#xff1a;Centos 7.9 数据库&#xff1a;mysql 8.0.30 需求&#xff1a;生产环境 mysql 数据&#xff08;约670MB&#xff09;备份。其中存在大字段、longblob字段 参考博客&#xff1a;Linux环境下使用crontab实现mysql定时备份 - 知乎 一、数据库备份 1. 备份脚本。创…

Python项目Flask ipv6双栈支持改造

一、背景 Flask 是一个微型的(轻量)使用Python 语言开发的 WSGI Web 框架(一组库和模块),基于Werkzeug WSGI工具箱/库和Jinja2 模板引擎,当然,Python的WEB框架还有:Django、Tornado、Webpy,这暂且不提。 Flask使用BSD授权。 Flask也被称为microframework(微框架),F…

RFID技术在工业智能制造生产线中的应用

随着自动化和信息化的快速发展&#xff0c;工业智能制造成为制造业的重要趋势&#xff0c;在制造商的生产线上&#xff0c;准确获取和管理工艺流程等各个环节的信息至关重要&#xff0c;作为物联网感知层的核心组成部分&#xff0c;RFID技术以其非接触式、无感知的特点&#xf…

隔山打牛:金融大崩溃

当2004-2006年美联储主席格林斯潘在任期的末尾一鼓作气把联邦利率从1%拉高到5%&#xff0c;然后把美联储主席的位子交给继任者伯南克的时候&#xff0c;没有人意识到接下来将要发生何等巨变。 图&#xff1a;美国联邦利率 伯南克把利率稳定在5.3%附近的高位一年左右时间&#x…

【ArcGIS】基本概念-矢量空间分析

栅格数据与矢量数据 1.1 栅格数据 栅格图是一个规则的阵列&#xff0c;包含着一定数量的像元或者栅格 常用的栅格图格式有&#xff1a;tif&#xff0c;png&#xff0c;jpeg/jpg等 1.2 矢量数据 矢量图是由一组描述点、线、面&#xff0c;以及它们的色彩、位置的数据&#x…

无涯教程-JavaScript - AVEDEV函数

描述 AVEDEV函数返回数据点与其平均值的绝对偏差的平均值。 AVEDEV是数据集中变异性的量度。 语法 AVEDEV (number1, [number2] ...)争论 Argument描述Required/OptionalNumber11 to 255 arguments for which you want the average of the absolute deviations.Requirednum…

趴趴雅思作文修改

前言 在网上试了下趴趴雅思作文修改的服务&#xff0c;淘宝上直接就可以购买&#xff0c;首次有优惠&#xff0c;之后还是挺贵的。 用了下感觉&#xff0c;有用还是有用的&#xff0c;但是挺贵的&#xff0c;一次40&#xff0c;不值。他给我作文的评分是7分&#xff0c;应该给…

fineReport11.0.4版本新建数据链接

需要以下几步&#xff1a; 1.设计器和服务器都需要安装对应数据库的驱动&#xff08;已安装就跳过&#xff09; 对应驱动可以在官网下载&#xff0c;百度搜下有教程 2.服务器没有驱动需要上传驱动 2.1 服务器上传驱动文件&#xff0c;需要修改finedb中的fine_conf_entity表…