排序算法

算法与数据结构——排序(六)堆排序

馋奶兔 提交于 2020-03-05 02:46:33
在前面的排序算法里面,我们发现每次找到一个最小的数都要进行很多次的比较,比如在n个数里面,我们如果想要找到最小的数,那么就需要比较 n-1次,那么我们想,能不能减少每次比较的次数呢。 其实发现是可以的,在前面的简单选择排序算法里面,我们每次找到最小的数后,剩余的一些数,其实有的是已经经过比较了的,所以在我们寻找第二小的数的时候,完全可以利用第一次的比较结果,但是由于我们没有把第一次比较的结果记录下来,所以我们在后面的比较过程中用不到,那么我们会想,能不能想办法把第一次比较的结果保存下来呢。办法肯定是有的,这就是今天我们要学习的堆排序。 那么什么是堆排序呢,我们首先要弄清楚什么是堆。看下面的两个图,它们都是堆: 通过图我们可以看出,它们的根结点,要么比他们的左右孩子都大,要么比他们的左右孩子都小。这就是堆。具体的定义就是: 堆是具有以下性质的完全二叉树,每个结点的值都大于或者等于其左右孩子结点的值,叫做大顶堆,每个结点的值都小于或者等于其左右孩子结点的值,叫做小顶堆。由二叉树的一个性质,我们可以知道,一个完全二叉树,如果它的根结点位置是i,那么它左孩子位置就是2i,右孩子位置就是2i+1,所以大顶堆可以定义为ki>=k2i并且ki>=k2i+1,小顶堆的符号刚刚相反。 把堆进行层序遍历装入数据组,是如下结果: 堆排序算法,就是把一个序列构造成一个大顶堆(此处以大顶堆为例)

排序算法之冒泡排序

回眸只為那壹抹淺笑 提交于 2020-03-04 11:38:12
排序算法之冒泡排序 分析思路 :冒泡排序,顾名思义就是像冒气泡一样,可以从前冒到后,也可以从后冒到前。这里以从后冒到前,从小到大排序举例:从最后一个值开始,不断将其与前一个值进行比较,如果后面的值比前面的值要小,那就进行交换,这样遍历一次之后,序列第一个位置就已经是最小的值了,如此循环,O(n2)之后就可以全部排好序。 编程思路 : 顺序存储:如果序列为数组,我们可以采用两重for循环。第一重for循环用于记录未排好序序列的起点,第二重for循环用于遍历、比较和交换。 链式存储:如果序列为链表,我们可以采用双指针。第一个指针用于记录未排好序子链的起点,第二个指针用于遍历、比较和交换。(链式存储只能从前冒到后) 具体代码 : 顺序存储 void Emit_Bubble_Sort(int array[],int n) { for (int i = 0; i < n; i++) { for (int j = n-1; j > 0; j--) { if (array[j] < array[j - 1]) { int temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } } } 链式存储 void Emit_Bubble_Sort(Node *Head) { Node *p=Head->next,*q=Head-

排序算法分类

若如初见. 提交于 2020-03-04 09:29:11
排序分类 内部排序:指将所有数据加载到内存中进行排序 插入排序:1.直接插入排序 2.希尔排序 选择排序:1.简单选择排序 2.堆排序 交换排序:1.冒泡排序 2.快速排序 归并排序 基数排序 外部排序:内存 + 磁盘 时间频度 介绍: 一个算法花费的时间与算法中语句执行的次数成正比例。哪个算法中语句执行次数越多,它话费的时间就多。一个算法中的语句执行次数成为语句频度或时间频度。记为T(n) 时间复杂度 一般情况下,算法中的基本操作语句的重复执行次数是问题规模n的某个函数,用T(n)表示,若有某个辅助行数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级行数。记作T(n) = O(f(n)),称O(f(n))成为算法的渐进时间复杂度,简称时间复杂度。 计算时间复杂度的方法: 用常数1代替运行时间中所有的常数 修改后的运行次数函数中,只保留最高阶项 去除最高阶项的系数 来源: CSDN 作者: ZhongJinHacker- 链接: https://blog.csdn.net/u012913972/article/details/104646760

全排序

独自空忆成欢 提交于 2020-03-04 07:43:26
可以想象有4个盒子分别放4样或3样物品。 A44:第一个物品有4种放法,第二个3种,第三个2种,最后一个1种,所以4*3*2*1=24种。 A43:第一个物品有4种放法,第二个3种,第三个2种,所以4*3*2=24种。 还可以套公式 ANR = n/(n-r) A44 = 4*3*2*1 / 0= 24 ( 0的阶乘=1) A43 = 4*3*2*1 / 1= 24( 1的阶乘也=1) 扩展资料: 全排列的计算方法: 字典序法 对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。 [例]字符集{1,2,3},较小的数字较先, 这样按字典序生成的全排列是:123,132,213,231,312,321。 [注意] 一个全排列可看做一个字符串,字符串可有前缀、后缀。 1)生成给定全排列的下一个排列 所谓一个的下一个就是这一个与下一个之间没有其他的。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。 [例]839647521是1--9的排列。 1—9的排列最前面的是123456789,最后面的是987654321,从右向左扫描若都是增的,就到987654321,也就没有下一个了。否则找出第一次出现下降的位置。 邻位对换法 递减进位制数法的中介数进位不频繁,求下一个排列在不进位的情况下很容易。 这就启发我们

常用排序算法之交换排序 ( 冒泡排序、快速排序 )

ⅰ亾dé卋堺 提交于 2020-03-04 07:21:58
利用交换数据元素的位置进行排序的方法称为交换排序。 常用的交换排序方法有冒泡排序和快速排序。快速排序是一种分区交换排序方法。 冒泡排序 方法:设数组a中存放了n个数据元素,循环进行n-1次如下的排序过程:第1次时,依次比较相邻两个数据元素 a[i].key 和 a[i+1].key ( i = 0,1,2,...,n-1 ),若为逆序,即 a[i].key > a[i+1].key ,则交换两个数据元素,否则不交换,这样数值最大的数据元素将被放置在 a[n-1] 中。第2次时,数据元素个数减1,即数据元素个数为 n-1 ,操作方法和第1次类似,这样整个n个数据元素集合中的数值较大的数据元素将被放置在 a[n-2] 中。当第 n-1 次结束时,整个n个数据元素集合中次小的数据元素将被放置在 a[1] 中,a[0] 中放置了最小的数据元素。有些待排序的数据元素序列已基本有序,这样实际上并不需要全部执行完上述过程数据元素已经全部排好序。在算法设计中设计一个flag变量,flag变量用于标记本次交换排序过程中是否有交换动作,若本次交换排序过程没有交换动作,则说明数据元素已全部排好序,就可提前结束排序过程。 C++实现: BubbleSort.cpp 1 void BubbleSort( DataType a[], int n ) 2 { 3 int i, j, flag = 1; 4

归并排序与快速排序模板与图解笔记(转载)

ⅰ亾dé卋堺 提交于 2020-03-04 07:20:10
https://blog.csdn.net/zpznba/article/details/83745205 C++ 归并排序与快速排序 2018年11月05日 15:15:31 zpznba 阅读数 948 归并排序: 【算法逻辑】 归并的思路(分治)是把一个大问题a拆解成两个小问题b和c,解决了两个子问题再整合一下,就解决了原问题。用递归的方法,先分解再合并(分治是一种解决问题的处理思想,递归是一种编程技巧,这两者并不冲突): 【代码实现】 # include <iostream> using namespace std; void Merge ( int arr[], int l, int q, int r){ int n=r-l+ 1; //临时数组存合并后的有序序列 int* tmp= new int[n]; int i= 0; int left=l; int right=q+ 1; while(left<=q && right<=r) tmp[i++] = arr[left]<= arr[right]?arr[left++]:arr[right++]; while(left<=q) tmp[i++]=arr[left++]; while(right<=r) tmp[i++]=arr[right++]; for( int j= 0;j<n;++j) arr[l+j]=tmp

算法图解|选择排序和递归

帅比萌擦擦* 提交于 2020-03-03 22:30:30
一:选择排序,O(n2) 选择排序是一种灵巧的算法,但其速度不是很快 代码示例: # 选择排序:O(nxn) # 找出数组中最小的元素 def findsmallest(arr): # 假设小值为arr[0] smallest = arr[0] # 存储最小元素的索引 smallest_index = 0 # O(n) for i in range(1, len(arr)): if arr[i] < smallest: smallest = arr[i] smallest_index = i return smallest_index # 对数组进行选择排序 def selectionSort(arr): newArr = [] # O(nxn) for i in range(len(arr)): smallest_index = findsmallest(arr) # 将该索引的元素添加到newArr newArr.append(arr.pop(smallest_index)) return newArr print(selectionSort([1, 8, 6, 9, 10])) # [1, 6, 8, 9, 10] 二:递归 问题:有个盒子里有盒子,而盒子里的盒子又有盒子。钥匙就在某个盒子中。怎么能找到钥匙。 代码示例: 第一种方法: 详细检查盒子内的东西

js的冒泡排序和选择排序

邮差的信 提交于 2020-03-03 19:48:41
冒泡排序 概念 依次对数组中相邻数字进行比较(两两比较),大的放后面 学前准备 思考1 : i < arr.length 是遍历几次 i < arr.length-1 是遍历几次 思考2 : 交换两个变量 思考3 :数组中的最大值放到最后 var arr = [5, 4, 3, 2, 1]; 冒泡排序算法 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。 在这一点,最后的元素应该会是最大的数。 针对所有的元素重复以上的步骤,除了最后一个。 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 代码实现 var arr = [5,99,2,9,1,5,67,7,10,23]; //定义一个杂乱的数组 for(var i=0;i<arr.length-1;i++){ //大循环,用于遍历数组每个元素 for(var j=0;j<arr.length-i-1;j++){ //小循环,用于将数组中的某个元素与其它所有元素相比较 var sum; //声明一个局部变量,当作第三个空瓶子 if(arr[j]>arr[j+1]){ //判断当前元素和后一个元素的大小,如果当前元素比后一个元素大 sum = arr[j+1]; //将后一个元素(小元素)放在空瓶子里 arr[j+1] = arr[j]; /

用c++实现冒泡排序

本秂侑毒 提交于 2020-03-03 16:27:42
标题冒泡排序是一个经典的算法,简单来说用嵌套循环就能实现 现在假设有一个数组[3,5,7,2,4],那么如果要想把它用冒泡从小到大排序, 首先取3和5比较,3小于5;用5和7比较,5小于7;用7和2比较,7大于2;用7和4比较,7大于4; 第0轮比下来数组变为[3,5,2,4,7],比较了 5-1 次; 第1轮还是依次比较数组变为[3,2,4,5,7],比较了 5-2 次; 第2轮数组变为[2,3,4,5,7],比较了 5-3 次,此时发现数组已经从小到大排序,但是由于数组有5个数,所以两两比较,需要比较5-1轮,在每一轮比较的内部循环中,需要比较5-1-排序轮数。 所以结论是:排序总轮数 = 元素个数 - 1; 每轮对比次数 = 元素个数 - 1 - 排序轮数; c++代码如下: # include <iostream> using namespace std ; int main ( ) { int a [ 5 ] = { 2 , 4 , 6 , 7 , 3 } ; int temp = 0 ; for ( int i = 0 ; i < size ( a ) - 1 ; i ++ ) { for ( int j = 0 ; j < size ( a ) - 1 - i ; j ++ ) { if ( a [ j ] > a [ j + 1 ] ) { temp = a [ j

数据结构-快速排序 归并排序

£可爱£侵袭症+ 提交于 2020-03-03 16:03:46
文章目录 归并排序 (Merge sort) 简介 代码 性能分析 快速排序(Quick sort) 简介 代码 性能分析 排序算法的结合 总结 注:所有的代码在我的 Github 中有均具体C++代码实现。 这里主要讲的是时间复杂度为O(nlogn)的两种排序算法:快速排序(Qiuck sort)和 归并排序 (Merge sort)。 这两种排序都是用了分治的思想,我们因此可以借鉴这个思想来解决非排序的一些问题,例如: 如何在O(n)的时间复杂度内查找一个无序数组中的第K大的元素? 归并排序 (Merge sort) 简介 简单地说,如果要排序一个数组,我们首先吧数组从中间分成前后两个部分,然后对前后两个部分分别排序,最后将排序好的两部分进行合并。 这里使用了分治的思想,也就是分而治之,将一个大问题分成几个小的子问题来解决,小的问题解决了,大的问题也就解决了。 这里,主要就是merge函数的实现问题了, merge(A[p...r], A[p...q], A[q+1...r]) 也就是将已经有序的 A[p...q] 和 A[q+1...r] 合并成一个有序的数组,这里我们使用了一个额外的临时数组,其空间带下为 r - p + 1 ,具体操作如下: 代码 void merge(int arr[], int l, int m, int r) { int n = r - l + 1;