排序算法总结

莫队算法·初探总结

爷,独闯天下 提交于 2020-03-26 19:09:36
莫队算法分那么几类: 普通序列 带修改 树上 回滚 支持在线 其实上述的类型还可以组合起来( 非常的毒瘤 )。 个人理解莫队算法的精髓在于如何利用暴力将答案再合理的时间和空间内跑出来。说白了: \[莫队算法=一种很牛逼的自定义排序+分块处理+暴力 \] 首先要理解自定义排序,这个排序之后整个序列可以最快地处理所有的询问(这里暂时不谈第五类问题(支持在线),这里认为莫队是只能离线处理问题的,必须先把所有的问题都离线下来)。怎么为之快,快要看左端点移动的总距离+右端点移动的总距离最小。那么一般用块的奇偶性来排序就够快了。如下: bool cmp(const node &a,const node &b) { return (p[a.l]^p[b.l])?(p[a.l]<p[b.l]):((p[a.l]&1)?(a.r<b.r):(a.r>b.r)); } 排完序后大致移动的次数就在可控的范围内了。 其次是分块,因为一般这种序列题的复杂度是 \(O(\frac{n^2}{S}+mS)\) ( \(n\) 是序列长度, \(m\) 是询问次数, \(S\) 是块大小)。 那么用均值不等式去分析这个复杂度就好了。一般 \(n\) , \(m\) 同阶的时候取 \(\sqrt n\) 最优,但是假如 \(n\) 和 \(m\) 有别的情况的话具体分析,有时候还要决定用时间换空间来保证空间也过得去

八大排序算法总结

孤街浪徒 提交于 2020-03-26 05:29:24
排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。 常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。 本文将依次介绍上述八大排序算法。 算法一:插入排序 插入排序示意图 插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。 算法步骤 : 1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。 2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。) 代码实现: void insert_sort(int array[],unsignedint n) { int i,j; int temp; for(i = 1;i < n;i++) { temp = array[i]; for(j = i;j > 0&& array[j - 1] > temp;j--) { array[j]= array[j - 1]; } array[j] = temp; } } 算法二:希尔排序 希尔排序示意图 希尔排序 ,也称

代码题(32)— 排序算法总结

Deadly 提交于 2020-03-26 04:41:17
0、几种排序对比   1. 从平均时间来看,快速排序是效率最高的,但快速排序在最坏情况下的时间性能不如堆排序和归并排序。而后者相比较的结果是,在n较大时归并排序使用时间较少,但使用辅助空间较多。   2. 上面说的简单排序包括除希尔排序之外的所有冒泡排序、插入排序、简单选择排序。其中 直接插入排序最简单,但序列基本有序或者n较小时,直接插入排序是好的方法 ,因此常将它和其他的排序方法,如快速排序、归并排序等结合在一起使用。 一、交换排序 1、冒泡排序   思想 :对待排序元素的关键字从后往前进行多遍扫描,遇到相邻两个关键字次序与排序规则不符时,就将这两个元素进行交换。这样关键字较小的那个元素就像一个泡泡一样,从最后面冒到最前面来。   时间复杂度 :最坏:O(n2); 最好: O(n); 平均: O(n2)   空间复杂度 :O(1)   稳定性 : 稳定 ,相邻的关键字两两比较,如果相等则不交换。所以排序前后的相等数字相对位置不变。 void BubbleSort(vector<int> &a, int num) { bool flag = true; for (int i = 0; i < num ; ++i) { if (!flag)//判断上一次循环有没有交换 break; flag = false; for (int j = num - 1; j > i; --j) {

排序算法总结

瘦欲@ 提交于 2020-03-26 00:16:47
到目前为止,已经学习了十种不同的排序算法,它们各自为各自的优缺点,也有各自的适用环境,下面就来总结一些这些算法。 选择排序是拿一个数与其他的数进行比较,找到其他数中最小的一个数,然后把这个数与其他数中最小的一个数进行交换,依次循环。从这个过程中我们可以知道它的时间复杂度为O(N 2 ),最好和最坏的情况都是这么多,而且它是一种稳定的排序算法。 冒泡排序是把相邻的两个数进行比较,如果后面一个比前面的小,那么就交换它们的位置,依次循环。冒泡排序的时间复杂度为O(N 2 ),在最好的情况下,也就是待排序列有序的情况下,使用改进的冒泡排序算法,时间复杂度可为O(N)。冒泡排序也是一种稳定的排序方法。 插入排序,每次在插入时,先把这个数与要插入位置前面的数进行比较,如果比它大,那么直接插入到当前位置,如果比它小,那么把这个数与前面的数一直比较,直到找到一个比它小的数,把当前数插入到比它小的数的后面。插入排序时间复杂度为O(N 2 ),最好情况为O(N),它也是一种稳定的排序算法。 希尔排序是一种改进的插入排序,它是跳跃形式的,所以它是不稳定的排序,它的时间复杂度最好的情况是O(LogN 1.3 )。 堆排序是利用堆这个数据结构来进行排序的,每次移走堆顶的元素,然后再把剩下的元素构建成一个堆,这样一直循环,直到最后一个元素为止。堆排序的时间复杂度是O(NLongN),最好与最坏的情况都是这样

排序算法总结(一)插入排序【Insertion Sort】

生来就可爱ヽ(ⅴ<●) 提交于 2020-03-17 18:21:45
最近在忙着找工作,以前看的排序算法都忘记了,悲剧啦T T现在来回顾一下吧。 这边推荐一个算法可视化的网站,非常有用。http://visualgo.net/ 一.插入排序的思想(Wikipedia):   它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素(已排序)大于新元素,将该元素移到下一位置 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置 将新元素插入到该位置后 重复步骤2~5 Tips:如果 比较操作 的代价比 交换操作 大的话,可以采用二分查找来减少 比较操作 的数目。该算法可以认为是 插入排序 的一个变种,称为二分查找插入排序。 二:过程 原始数据 如下图所示,第一个数设为已排序完成的数,此时将需要排序的数往前进行比较,如果已排序的数(11)大于改元素(5),则将已排序的数后移一位(11),直到找到比自己(5)小的数或则到达数组的头部。 重复上述过程 三.代码 #include <iostream> #include <vector>

python排序算法总结和实现

风流意气都作罢 提交于 2020-03-12 11:46:30
------------------希尔排序------------- 一直没搞懂希尔排序怎么搞得 def Shell_sort(L): step = len(L)/2 while step > 0: for i in range(step,len(L)): #在索引为step到len(L)上,比较L[i]和L[i-step]的大小 while(i >= step and L[i] < L[i-step]): #这里可以调整step从小到大或者从大到小排列 L[i],L[i-step] = L[i-step],L[i] i -= step step /= 2 print L Shell_sort(L) ------------------插入排序------------- 一个有序数列,一个无序数列,遍历无序数列,把数据插入到有序数列的相应位置 def insertion_sort(A): length=len(A) for i in range(1,length): key=A[i] j=i-1 while j>0 and A[j]>key: A[j+1]=A[j] j=j-1 A[j+1]=key return A ------------------冒泡排序------------- 比较相邻的两个元素,保证每次遍历到最后的元素是最大的 def bubble_sort(A):

排序算法总结二

偶尔善良 提交于 2020-03-02 18:06:31
本文接排序算法总结一 3. 冒泡排序 冒泡排序的基本思想:以正序排列为例,我们首先要将最大的数沉到最底下,从第一个数开始,比较相邻的两个数,如果为逆序则交换这两个数,重复这个操作直到倒数第二个数,此时最大的数已沉到最底下;然后再从第一个数开始,用同样的方法将次大的数沉到次底下,重复这个过程直到排序成功。代码如下: void PaoSort1(vector<int>& a) { int length = a.size(); for (int i = 0; i < length - 1; i++) { for (int j = 0; j < length -1-i; j++) { if (a[j]>a[j+1]) Swap(a[j], a[j+1]); } } } 注意上面的内循环j的判断条件,每当外部循环i加1表示,底部多了一个数,所以j跳出条件为length-1-i,这个过程其实是泡沫沉底。而真正的冒泡是从底部向上升,这个过程与沉底类似,只不过内部循环中的j从最后一个数开始,每次循环后j值递减,而循环跳出条件为j<i. 上述代码的缺点是当序列已经有序了,而循环没有结束,会继续进行比较操作,这样便增加了运行时间。为了提高速度我们可以设置一个标记来查看是否进行了交换,并把这个标签加入到外部循环的判断条件,这样如果没有交换说明已经排序完成,程序返回。代码如下: void Paosort2

十大经典算法排序总结对比

ぐ巨炮叔叔 提交于 2020-02-28 13:31:56
十大经典算法排序总结对比 一张图概括: 主流排序算法概览 名词解释: n : 数据规模 k :“桶”的个数 In-place : 占用常数内存,不占用额外内存 Out-place : 占用额外内存 稳定性 :排序后2个相等键值的顺序和排序之前它们的顺序相同 冒泡排序(Bubble Sort) 冒泡排序须知: 作为最简单的排序算法之一,冒泡排序给我的感觉就像Abandon在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。。。冒泡排序还有一种优化算法,就是立一个flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。但这种改进对于提升性能来说并没有什么太大作用。。。 什么时候最快(Best Cases): 当输入的数据已经是正序时(都已经是正序了,我还要你冒泡排序有何用啊。。。。) 什么时候最慢(Worst Cases): 当输入的数据是反序时(写一个for循环反序输出数据不就行了,干嘛要用你冒泡排序呢,我是闲的吗。。。) 冒泡排序动图演示: 冒泡排序JavaScript代码实现: function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len; i++) { for (var j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j+1])

算法归总—常用排序算法总结

一世执手 提交于 2020-02-08 04:10:35
这次总结一下常用的一些排序用的算法,目前只是一部分,包括: 冒泡排序、桶排序、选择排序、插入排序、快速排序 (一)冒泡排序 冒泡排序是一种稳定的排序方法,因为如果两个相邻的数相同的话,将不会有所交换。 思路是比较两个相邻的数字,比较大的放在右边。 如果一共有n个数字,那么第一次则需要比较n-1次,然后比较的次数依次递减。 第一次比较,将最大的数放到了最后,第二次比较,将倒数第二个最大的数放到了倒数第二的位置,第三次比较将倒数第三最大的数放到了倒数第三的位置,以此类推,比较到最后得到的就是真正的顺序。 #include<bits/stdc++.h> using namespace std; int num[15]; int main() { int n; cin>>n; //输入所要排序的数字的个数 for(int i = 1;i<=n;i++){ cin>>num[i]; //输入需要排列的数字 } for(int i = n-1;i>=1;i--){ //进行冒泡排序操作 for(int j = 1;j<=i;j++){ if(num[j]>num[j+1]){ num[j] = num[j]^num[j+1]; num[j+1] = num[j]^num[j+1]; num[j] = num[j]^num[j+1]; } } } for(int i = 1;i<=n;i++){

经典排序算法总结及关键代码(c++)

蹲街弑〆低调 提交于 2020-01-28 03:56:34
主要是理解动图,结合图和代码来分析理解。 冒泡排序 平均复杂度:O(n2) 空间复杂度:O(1) 稳定性:稳定 冒泡排序 是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 void Bubblesort(vector<int>& a,int n) { for(int i=n-1; i>0; i--) for(int j=0; j<i; j++) { if(a[j]>a[j+1]) swap(a[j],a[j+1]); } } 选择排序 平均复杂度:O(n2) 空间复杂度:O(1) 稳定性:不稳定 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕 vector<int> selectionSort(vector<int>& a) { if (a.size() == 0) return a; for (int i = 0; i < a.size(); i++) { int minIndex = i; for (int j = i; j < a.size(); j++)