常用排序算法总结 - iamfranter的专栏 - 博客频道 - CSDN

合集下载

排序算法总结-各种排序算法总结含代码【汇总】

排序算法总结-各种排序算法总结含代码【汇总】

排序算法总结|各种排序算法总结含代码【汇总】/2016/0901/20160901093343273.jpg" width="560" alt="排序算法总结" />插入排序原理依次选择一个待排序的数据,插入到前边已排好序的序列中。

性能时间复杂度为O(N),空间复杂度为O(1)。

算法是稳定的,比较次数和交换次数都与初始序列有关。

优化直接插入排序每次往前插入时,是按顺序依次往前找,可在这里进行优化,往前找合适的插入位置时采用二分查找的方式,即折半插入。

折半插入排序相对直接插入排序而言:平均性能更快,时间复杂度降至O(NlogN),排序是稳定的,但排序的比较次数与初始序列无关,总是需要foor(log(i))+1次排序比较。

使用场景当数据基本有序时,采用插入排序可以明显减少数据交换和数据移动次数,进而提升排序效率。

代码希尔排序原理插入排序的改进版,是基于插入排序的以下俩点性质而提出的改进方法:插入排序对几乎已排好序的数据操作时,效率很高,可以达到线性排序的效率。

但插入排序在每次往前插入时只能将数据移动一位,效率比较低。

所以希尔排序的思想是:先是取一个合适的gap缩小间隔gap,例如去gap=ceil(gap/2),重复上述子序列划分和排序直到,最后gap=1时,将所有元素放在同一个序列中进行插入排序为止。

性能开始时,gap取值较大,子序列中的元素较少,排序速度快,克服了直接插入排序的缺点;其次,gap值逐渐变小后,虽然子序列的元素逐渐变多,但大多元素已基本有序,所以继承了直接插入排序的优点,能以近线性的速度排好序。

代码选择排序原理每次从未排序的序列中找到最小值,记录并最后存放到已排序序列的末尾性能时间复杂度为O(N),空间复杂度为O(1),排序是不稳定的(把最小值交换到已排序的末尾导致的),每次都能确定一个元素所在的最终位置,比较次数与初始序列无关。

排序算法总结

排序算法总结

排序算法总结排序算法是计算机科学中的一个重要主题,它是对一组数据进行排序的过程。

排序算法可以分为内部排序和外部排序两种类型。

内部排序是指所有数据都在内存中进行排序,而外部排序是指数据太大,无法全部存储在内存中,需要借助外部存储器进行排序。

常见的内部排序算法有冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序和基数排序等。

下面对这些算法进行总结。

1. 冒泡排序冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就交换它们的位置。

时间复杂度为O(n^2)。

2. 选择排序选择排序是一种简单直观的排序算法,它的基本思想是每次从未排序的数据中选择最小(或最大)的一个元素,存放到已排序的数据序列的末尾。

时间复杂度为O(n^2)。

3. 插入排序插入排序是一种简单直观的排序算法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增加1的有序表。

时间复杂度为O(n^2)。

4. 希尔排序希尔排序是一种基于插入排序的快速排序算法,它的基本思想是将待排序的数组按照一定的间隔分成若干个子序列,对每个子序列进行插入排序,然后逐步缩小间隔,直到间隔为1,最后对整个数组进行插入排序。

时间复杂度为O(nlogn)。

5. 归并排序归并排序是一种稳定的排序算法,它的基本思想是将待排序的数组分成若干个子序列,每个子序列都是有序的,然后再将子序列合并成一个有序的序列。

时间复杂度为O(nlogn)。

6. 快速排序快速排序是一种常用的排序算法,它的基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

时间复杂度为O(nlogn)。

7. 堆排序堆排序是一种树形选择排序算法,它的基本思想是将待排序的数组构建成一个大根堆或小根堆,然后依次将堆顶元素与堆底元素交换,再重新调整堆,直到整个数组有序。

数据结构算法排序总结

数据结构算法排序总结

数据结构算法排序总结在计算机科学中,排序是一种对数组或列表等数据进行排序的重要算法,它是程序设计语言和数据库语言的基础之一。

排序算法将数据按照一定的顺序排列,这样可以更方便地进行查找、比较和统计等操作,提高运算效率。

常用的排序算法主要有冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序等。

下面将对这些排序算法进行总结。

1.冒泡排序冒泡排序是一种最基本的排序算法,其思想是通过不断比较相邻的元素,如果前一个元素大于后一个元素,则将它们交换位置。

每一轮排序会使得最大的元素浮到数组的顶部。

时间复杂度为O(n^2)。

2.选择排序选择排序是一种简单的排序算法,其思想是每次从未排序的元素中选择最小(或最大)的元素,并将其放到已排序的序列的末尾。

时间复杂度为O(n^2)。

3.插入排序插入排序是一种简单直观的排序算法。

其思想是将一个数插入到一个有序的数组中,使得插入后依然保持有序。

时间复杂度为O(n^2)。

4.归并排序归并排序是一种分治法的排序算法,它将一个大的问题分成若干个小的问题进行解决。

归并排序的基本思想是将待排序数组递归地分成两个阶段,然后对每个阶段进行排序,最后将两个有序的数组合并成一个有序的数组。

时间复杂度为O(nlogn)。

5.快速排序6.希尔排序希尔排序是一种改进版的插入排序。

其思想是通过设定“间隔”来进行排序,将序列分成若干个子序列,对每个子序列进行插入排序。

希尔排序的时间复杂度介于O(n)和O(n^2)之间。

7.堆排序总结:不同的排序算法各有特点,在不同的情况下可采用不同的排序算法。

对于大型数据集合,推荐使用快速排序、归并排序和堆排序;对于小型数据集合,推荐使用插入排序、冒泡排序和选择排序。

无论使用哪种排序算法,当数据集中包含较多重复的元素时,它们的表现都不如理想,因为它们需要进行多次比较和交换以移动相同的元素。

因此在实际应用中,需要根据数据集的特点选择相应的排序算法。

数据结构-各类排序算法总结

数据结构-各类排序算法总结

数据结构-各类排序算法总结原文转自:/zjf280441589/article/details/38387103各类排序算法总结一. 排序的基本概念排序(Sorting)是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个项值有序的序列。

有n 个记录的序列{R1,R2,…,Rn},其相应关键字的序列是{K1,K2,…,Kn},相应的下标序列为1,2,…,n。

通过排序,要求找出当前下标序列1,2,…,n 的一种排列p1,p2,…,pn,使得相应关键字满足如下的非递减(或非递增)关系,即:Kp1≤Kp2≤…≤Kpn,这样就得到一个按关键字有序的记录序列{Rp1,Rp2,…,Rpn}。

作为排序依据的数据项称为“排序码”,也即数据元素的关键码。

若关键码是主关键码,则对于任意待排序序列,经排序后得到的结果是唯一的;若关键码是次关键码,排序结果可能不唯一。

实现排序的基本操作有两个:(1)“比较”序列中两个关键字的大小;(2)“移动”记录。

若对任意的数据元素序列,使用某个排序方法,对它按关键码进行排序:若相同关键码元素间的位置关系,排序前与排序后保持一致,称此排序方法是稳定的;而不能保持一致的排序方法则称为不稳定的。

二.插入类排序1.直接插入排序直接插入排序是最简单的插入类排序。

仅有一个记录的表总是有序的,因此,对n 个记录的表,可从第二个记录开始直到第n 个记录,逐个向有序表中进行插入操作,从而得到n个记录按关键码有序的表。

它是利用顺序查找实现“在R[1..i-1]中查找R[i]的插入位置”的插入排序。

注意直接插入排序算法的三个要点:(1)从R[i-1]起向前进行顺序查找,监视哨设置在R[0];[cpp] viewplaincopyR[0] = R[i]; // 设置“哨兵”for (j=i-1; R[0].key<R[j].key; --j) // 从后往前找return j+1; // 返回R[i]的插入位置为j+1 (2)对于在查找过程中找到的那些关键字不小于R[i].key 的记录,可以在查找的同时实现向后移动,即:查找与移动同时进行.[cpp] view plaincopyfor (j=i-1; R[0].key<R[j].key; --j){R[j+1] = R[j];} (3)i = 2,3,…, n, 实现整个序列的排序(从i = 2开始).【算法如下】[cpp] viewplaincopy//C++代码,确保能够运行void insertionSort(int *R,int length){for (int i = 2; i <= length; ++i){R[0] = R[i]; //设为监视哨int j;for (j = i-1; R[0] < R[j]; --j){R[j+1] = R[j]; //边查找边后移}R[j+1] = R[0]; // 插入到正确位置}} 【性能分析】(1)空间效率:仅用了一个辅助单元,空间复杂度为O(1)。

排序算法总结

排序算法总结

排序算法总结排序算法是计算机科学中最基础且常用的算法之一。

它们的作用是将一组数据按照指定的顺序进行排列。

根据数据量的大小和特点,选择适合的排序算法可以提高程序的性能。

常见的排序算法有冒泡排序、插入排序、选择排序、希尔排序、归并排序、快速排序、堆排序和计数排序等。

冒泡排序是最简单、最直观的排序算法。

它通过多次比较相邻的元素,将较大的数往后移动,将较小的数往前移动,从而实现排序。

但是冒泡排序的时间复杂度较高,为O(n^2)。

插入排序的思想是将数组分为有序区和无序区,每次将无序区的第一个元素插入到有序区的合适位置。

它的时间复杂度也为O(n^2),但在实际应用中对小规模数据进行排序时表现良好。

选择排序每次从数组中选择最小的元素,与数组的第一个元素交换位置,然后从剩下的元素中选择最小的元素,与数组的第二个元素交换位置,依此类推。

它的时间复杂度也为O(n^2),但它的交换次数相对较少。

希尔排序是直接插入排序的改进版,它将数组按照一定的步长进行分组,对每组进行插入排序,然后缩小步长,直到步长为1,最后再进行一次插入排序。

希尔排序的时间复杂度介于O(n^1.3)和O(n^2)之间,具体取决于步长的选择。

归并排序是一种稳定且分治的排序算法,它将数组分为两个子数组,分别对子数组进行排序,然后将排好序的子数组合并成一个有序的数组。

归并排序的时间复杂度为O(nlogn),但需要额外的空间来存储临时数组。

快速排序是一种高效且不稳定的排序算法,它通过选取一个基准元素,将数组分为左右两个子数组,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素,然后在左右子数组中递归地进行快速排序。

快速排序的时间复杂度为O(nlogn),但在最坏情况下可能达到O(n^2)。

堆排序利用堆这种数据结构进行排序。

堆排序的思想是将数组构建成一个最大堆或最小堆,然后将堆顶的元素与数组的最后一个元素交换位置,再对剩余的元素进行调整,再重复执行这个过程。

各种排序方法总结

各种排序方法总结

选择排序、‎快速排序、‎希尔排序、‎堆排序不是‎稳定的排序‎算法,冒‎泡排序、插‎入排序、归‎并排序和基‎数排序是稳‎定的排序算‎法。

‎冒泡法‎:这‎是最原始,‎也是众所周‎知的最慢的‎算法了。

他‎的名字的由‎来因为它的‎工作看来象‎是冒泡:‎复杂度为‎O(n*n‎)。

当数据‎为正序,将‎不会有交换‎。

复杂度为‎O(0)。

‎直接插‎入排序:O‎(n*n)‎选择排‎序:O(n‎*n)‎快速排序:‎平均时间复‎杂度log‎2(n)*‎n,所有内‎部排序方法‎中最高好的‎,大多数情‎况下总是最‎好的。

‎归并排序:‎l og2(‎n)*n‎堆排序:‎l og2(‎n)*n‎希尔排序‎:算法的复‎杂度为n的‎1.2次幂‎‎这里我没‎有给出行为‎的分析,因‎为这个很简‎单,我们直‎接来分析算‎法:首‎先我们考虑‎最理想的情‎况1.‎数组的大小‎是2的幂,‎这样分下去‎始终可以被‎2整除。

假‎设为2的k‎次方,即k‎=log2‎(n)。

‎2.每次‎我们选择的‎值刚好是中‎间值,这样‎,数组才可‎以被等分。

‎第一层‎递归,循环‎n次,第二‎层循环2*‎(n/2)‎.....‎.所以‎共有n+2‎(n/2)‎+4(n/‎4)+..‎.+n*(‎n/n) ‎= n+n‎+n+..‎.+n=k‎*n=lo‎g2(n)‎*n所‎以算法复杂‎度为O(l‎o g2(n‎)*n) ‎其他的情‎况只会比这‎种情况差,‎最差的情况‎是每次选择‎到的mid‎d le都是‎最小值或最‎大值,那么‎他将变成交‎换法(由于‎使用了递归‎,情况更糟‎)。

但是你‎认为这种情‎况发生的几‎率有多大?‎?呵呵,你‎完全不必担‎心这个问题‎。

实践证明‎,大多数的‎情况,快速‎排序总是最‎好的。

‎如果你担心‎这个问题,‎你可以使用‎堆排序,这‎是一种稳定‎的O(lo‎g2(n)‎*n)算法‎,但是通常‎情况下速度‎要慢于快‎速排序(因‎为要重组堆‎)。

排序的几种方式

排序的几种方式在日常生活中,我们经常需要对事物进行排序,以便更好地组织和理解信息。

排序是一种将元素按照一定的规则进行排列的方法,可以应用于各种领域,如数字排序、字母排序、时间排序等。

本文将介绍几种常用的排序方式,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。

一、冒泡排序冒泡排序是一种简单直观的排序方法,通过比较相邻元素的大小,将较大的元素逐渐“冒泡”到右侧,较小的元素逐渐“沉底”到左侧。

这个过程会不断重复,直到所有元素都按照升序排列。

冒泡排序的基本思想是从第一个元素开始,依次比较相邻的两个元素,如果前面的元素大于后面的元素,则交换它们的位置。

经过一轮比较后,最大的元素会“冒泡”到最右侧,然后再对剩下的元素进行相同的比较,直到所有元素都有序排列。

二、选择排序选择排序是一种简单直观的排序方法,它的基本思想是每次从待排序的元素中选择最小(或最大)的元素,放到已排序序列的末尾,直到所有元素都有序排列。

选择排序的过程可以分为两个部分:首先,在未排序的序列中找到最小(或最大)的元素,然后将其放到已排序序列的末尾;其次,将剩下的未排序序列中的最小(或最大)元素找到,并放到已排序序列的末尾。

这个过程会不断重复,直到所有元素都有序排列。

三、插入排序插入排序是一种简单直观的排序方法,它的基本思想是将待排序的元素逐个插入到已排序序列的适当位置,最终得到一个有序序列。

插入排序的过程可以分为两个部分:首先,将第一个元素看作已排序序列,将剩下的元素依次插入到已排序序列的适当位置;其次,重复上述过程,直到所有元素都有序排列。

插入排序的过程类似于整理扑克牌,将新抓到的牌插入到已有的牌中。

四、快速排序快速排序是一种常用的排序方法,它的基本思想是通过一趟排序将待排序序列分割成独立的两部分,其中一部分的所有元素都小于另一部分的所有元素。

然后对这两部分继续进行排序,直到整个序列有序。

快速排序的过程可以分为三个步骤:首先,从序列中选择一个基准元素;其次,将比基准元素小的元素放在左侧,比基准元素大的元素放在右侧;最后,递归地对左右两个部分进行排序。

十大排序算法总结

十大排序算法总结在计算机科学领域,排序算法是一个非常重要的研究方向。

排序算法可以帮助我们更快速、更有效率地处理大量数据。

在本文中,我们将介绍十大常见的排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序。

1. 冒泡排序冒泡排序是一种基本的排序算法。

它重复地遍历待排序的序列,一次比较两个元素,如果它们的顺序错误就交换位置,直到整个序列有序为止。

冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1)。

2. 选择排序选择排序是一种简单直观的排序算法。

它的工作原理是:首先在未排序的序列中找到最小元素,然后将其放到序列的起始位置;接着从剩余未排序的元素中继续寻找最小的元素,然后放到已排序序列的末尾。

选择排序的时间复杂度为O(n^2),空间复杂度为O(1)。

3. 插入排序插入排序是一种基本的排序算法。

它的工作原理是:将一个元素插入到已经排好序的序列中,使得插入后的序列仍然有序。

插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。

4. 希尔排序希尔排序是一种改进版的插入排序。

它通过比较距离较远的元素,可以快速地将大元素向右移动,从而减少后续排序的比较次数。

希尔排序的时间复杂度为O(nlogn),空间复杂度为O(1)。

5. 归并排序归并排序是一种分治算法。

它将待排序的序列分成若干个子序列,每个子序列都是有序的。

然后再将有序的子序列合并成最终的有序序列。

归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。

6. 快速排序快速排序是一种基于分治思想的排序算法。

它通过不断地将序列分成两个部分,将较小的元素移动到左边、较大的元素移动到右边,最终将整个序列排好序。

快速排序的时间复杂度为O(nlogn),空间复杂度为O(nlogn)。

7. 堆排序堆排序是一种基于堆的排序算法。

它将待排序的序列看成一棵完全二叉树,每个节点的值都不大于其父节点的值。

然后将最大值不断地从堆中取出,放到已排序序列的末尾。

十大经典排序算法(动图演示)

⼗⼤经典排序算法(动图演⽰)0、算法概述0.1 算法分类⼗种常见排序算法可以分为两⼤类:⽐较类排序:通过⽐较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为⾮线性时间⽐较类排序。

⾮⽐较类排序:不通过⽐较来决定元素间的相对次序,它可以突破基于⽐较排序的时间下界,以线性时间运⾏,因此也称为线性时间⾮⽐较类排序。

0.2 算法复杂度0.3 相关概念稳定:如果a原本在b前⾯,⽽a=b,排序之后a仍然在b的前⾯。

不稳定:如果a原本在b的前⾯,⽽a=b,排序之后 a 可能会出现在 b 的后⾯。

时间复杂度:对排序数据的总的操作次数。

反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执⾏时所需存储空间的度量,它也是数据规模n的函数。

1、冒泡排序(Bubble Sort)冒泡排序是⼀种简单的排序算法。

它重复地⾛访过要排序的数列,⼀次⽐较两个元素,如果它们的顺序错误就把它们交换过来。

⾛访数列的⼯作是重复地进⾏直到没有再需要交换,也就是说该数列已经排序完成。

这个算法的名字由来是因为越⼩的元素会经由交换慢慢“浮”到数列的顶端。

1.1 算法描述⽐较相邻的元素。

如果第⼀个⽐第⼆个⼤,就交换它们两个;对每⼀对相邻元素作同样的⼯作,从开始第⼀对到结尾的最后⼀对,这样在最后的元素应该会是最⼤的数;针对所有的元素重复以上的步骤,除了最后⼀个;重复步骤1~3,直到排序完成。

1.2 动图演⽰1.3 代码实现function bubbleSort(arr) {var len = arr.length;for (var i = 0; i < len - 1; i++) {for (var j = 0; j < len - 1 - i; j++) {if (arr[j] > arr[j+1]) { // 相邻元素两两对⽐var temp = arr[j+1]; // 元素交换arr[j+1] = arr[j];arr[j] = temp;}}}return arr;}2、选择排序(Selection Sort)选择排序(Selection-sort)是⼀种简单直观的排序算法。

排序算法 总结

排序算法总结排序算法是计算机科学中的一种基本算法,其目的是将一组数据按照一定规则进行排序,以便于后续的查找、统计和分析。

排序算法应用广泛,例如在数据库的索引、数据压缩、图形处理等领域都有重要的作用。

常见的排序算法可以分为两大类:比较排序和非比较排序。

比较排序通过比较元素的大小来确定元素的相对顺序,而非比较排序则不需要通过比较来确定元素的相对顺序。

比较排序算法的时间复杂度通常为O(nlogn),其中n表示待排序的元素个数。

最常见的比较排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序等。

这些算法的实现思路各不相同,但都是通过比较元素的大小来实现排序的。

冒泡排序是一种简单同时也是一种经典的比较排序算法。

其基本思想是从待排序的数据元素序列的起始端开始,依次比较两个相邻的元素,若前者大于后者,则交换这两个元素,直到整个序列的最大元素被排到了最后的位置。

然后,再针对剩余的元素重复该过程,直到整个序列都有序为止。

插入排序是一种简单而有效的比较排序算法。

其基本思想也是将待排序的数据元素序列分为两部分,一部分是已经排序好的元素,另一部分是待排序的元素。

然后,逐个将待排序的元素插入已排序的元素序列中,直到所有的元素都插入完成。

选择排序是一种简单而直观的比较排序算法。

其基本思想是将待排序的数据元素序列划分为已排序的元素和未排序的元素两部分,然后每次从未排序的元素中选取最小的元素,将其放置到已排序的元素序列的末尾。

如此重复,直到所有的元素都被放置到已排序的元素序列中。

快速排序是一种高效的比较排序算法,也是最常用的排序算法之一。

其基本思想是通过一趟排序将待排序的元素序列划分成独立的两部分,其中一部分的所有元素都比另一部分的所有元素小,然后再按照此方法对这两部分分别进行快速排序,最后将两部分排序好的元素序列拼接起来。

归并排序是一种稳定的比较排序算法,其基本思想是将待排序的元素序列分成两个长度相等的子序列,然后递归地对这两个子序列进行排序,最后再将这两个排好序的子序列逐个合并起来。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2014年5月6日常用排序算法总结 - iamfranter的专栏 - 博客频道 - 常用排序算法总结所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。

当待排序记录的关键字都不相同时,排序结果是惟一的,否则排序结果不惟一。

在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的;若具有相同关键字的记录之间的相对次序发生改变,则称这种排序方法是不稳定的。

要注意的是,排序算法的稳定性是针对所有输入实例而言的。

即在所有可能的输入实例中,只要有一个实例使得算法不满足稳定性要求,则该排序算法就是不稳定的。

一.插入排序插入排序的基本思想是每步将一个待排序的记录按其排序码值的大小,插到前面已经排好的文件中的适当位置,直到全部插入完为止。

插入排序方法主要有直接插入排序和希尔排序。

①.直接插入排序(稳定)接插入排序的过程为:在插入第i个记录时,R1,R2,..Ri-1已经排好序,将第i个记录的排序码Ki依次和R1,R2,..,Ri-1的排序码逐个进行比较,找到适当的位置。

使用直接插入排序,对于具有n个记录的文件,要进行n-1趟排序。

代码如下:1. void Dir_Insert(int A[],int N)2. {3. int j,t;4. for(int i=1;i<N;i++)5. {6. t=A[i];7. j=i-1;8. while(A[j]>t)9. {10. A[j+1]=A[j];11. j--;12. }13. A[j+1]=t;14. }15. }②.希尔排序(不稳定):希尔(Shell)排序的基本思想是:先取一个小于n的整数d1作为第一个增量把文件的全部记录分成d1个组。

所有距离为d1的倍数的记录放在同一个组中。

先在各组内进行直接插入排序;然后,取得第二个增量d2<d1重复上述的分组和排序,直至所取的增量di=1,即所有记录放在同一组中2014年5月6日常用排序算法总结 - iamfranter的专栏 - 博客频道 - 取得第二个增量d2<d1重复上述的分组和排序,直至所取的增量di=1,即所有记录放在同一组中进行直接插入排序为止。

该方法实质上是一种分组插入方法。

一般取d1=n/2,di+1=di/2。

如果结果为偶数,则加1,保证di为奇数。

希尔排序是不稳定的,希尔排序的执行时间依赖于增量序列,其平均时间复杂度为O(n^1.3).代码如下:1. void Shell(int A[],int n)2. {3. int i,j,k,t;4. (n/2)%2 == 0 ? k = n/2+1 : k = n/2;5. while(k > 0)6. {7. for(j=k;j<n; j++)8. {9. t = A[j];10. i = j - k;11. while(i>=0 && A[i]>t)12. {13. A[i+k]=A[i];14. i=i-k;15. }16. A[i+k]=t;17. }18. if(k == 1) break;19. (k/2)%2 ==0 ? k=k/2+1 : k=k/2;20. }21. }二.选择排序选择排序的基本思想是每步从待排序的记录中选出排序码最小的记录,顺序存放在已排序的记录序列的后面,直到全部排完。

选择排序中主要使用直接选择排序和堆排序。

①.直接选择排序(不稳定)直接选择排序的过程是:首先在所有记录中选出序码最小的记录,把它与第1个记录交换,然后在其余的记录内选出排序码最小的记录,与第2个记录交换......依次类推,直到所有记录排完为止。

无论文件初始状态如何,在第i趟排序中选出最小关键字的记录,需要做n-i次比较,因此,总的比较次数为n(n-1)/2=O(n^2)。

当初始文件为正序时,移动次数为0;文件初态为反序时,每趟排序均要执行交换操作,总的移动次数取最大值3(n-1)。

直接选择排序的平均时间复杂度为O(n^2)。

直接选择排序是不稳定的。

代码如下:1. void Dir_Choose(int A[],int n)2. {3. int k,t;4. for(int i=0;i<n-1;i++)5. {6. k=i;7. for(int j=i+1;j<n;j++)8. {9. if(A[j]<A[k]) k=j;10. }11. if(k!=i)12. {13. t=A[i];14. A[i]=A[k];15. A[k]=t;16. }17. }18. }②.堆排序(不稳定)堆排序是一种树形选择排序,是对直接选择排序的有效改进。

n个关键字序列K1,K2,...,Kn称为堆,当且仅当该序列满足(Ki<=K2i且Ki<=K2i+1)或(Ki>=K2i且Ki>=K2i+1),(1<=i<=n/2)。

根结点(堆顶)的关键字是堆里所有结点关键字中最小者,称为小根堆;根结点的关键字是堆里所有结点关键字中最大者,称为大根堆。

若将此序列所存储的向量R[1..n]看作是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。

堆排序的关键步骤有两个:一是如何建立初始堆;二是当堆的根结点与堆的最后一个结点交换后,如何对少了一个结点后的结点序列做调整,使之重新成为堆。

堆排序的最坏时间复杂度为O(nlog2n),堆排序的平均性能较接近于最坏性能。

由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录较少的文件。

堆排序是就地排序,辅助空间为O(1),它是不稳定的排序方法。

代码略..三.交换排序交换排序的基本思想是:两两比较待排序记录的排序码,并交换不满足顺序要求的那写偶对,直到满足条件为止。

交换排序的主要方法有冒泡排序和快速排序.①.冒泡排序(稳定的)冒泡排序将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为ki的气泡。

根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R;凡扫描到违反本原则的轻气泡,就使其向上"漂浮"。

如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。

冒泡排序的具体过程如下:第一步,先比较k1和k2,若k1>k2,则交换k1和k2所在的记录,否则不交换。

继续对k2和k3重复上述过程,直到处理完kn-1和kn。

这时最大的排序码记录转到了最后位置,称第1次起泡,共执行n-1次比较。

与第一步类似,从k1和k2开始比较,到kn-2和kn-1为止,共执行n-2次比较。

依次类推,共做n-1次起泡,完成整个排序过程。

若文件的初始状态是正序的,一趟扫描即可完成排序。

所需关键字比较次数为n-1次,记录移动次数为0。

因此,冒泡排序最好的时间复杂度为O(n)。

若初始文件是反序的,需要进行n-1趟排序。

每趟排序要进行n-i次关键字的比较(1<=i<=n-1),且每次比较都必须移动记录三次来达到交换记录位置。

在这种情况下,比较次数达到最大值n(n-1)/2=O(n^2),移动次数也达到最大值3n(n-1)/2=O(n^2)。

因此,冒泡排序的最坏时间复杂度为O(n^2)。

虽然冒泡排序不一定要进行n-1趟,但由于它的记录移动次数较多,故平均性能比直接插入排序要差得多。

冒泡排序是就地排序,且它是稳定的。

代码如下:1. void QP(int A[],int n)2. {3. int count=0,t,flag;4. for(int i=0;i<n-1;i++)5. {6. flag=0;7. for(int j=0;j<n-i;j++)8. {9. if(A[j+1]<A[j])10. {11. t=A[j];12. A[j]=A[j+1];13. A[j+1]=t;14. flag=1;15. count+=3;16. }17. }18. if(flag==0) break;19. }20. }②.快速排序:(不稳定的)快速排序采用了一种分治的策略,通常称其为分治法,其基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。

递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序的具体过程如下:第一步,在待排序的n个记录中任取一个记录,以该记录的排序码为准,将所有记录分成两组,第1组各记录的排序码都小于等于该排序码,第2组各记录的排序码都大于该排序码,并把该记录排在这两组中间。

第二步,采用同样的方法,对左边的组和右边的组进行排序,直到所有记录都排到相应的位置为止。

代码如下:1. void swap(int *a, int *b)2. {3. int temp = *a;4. *a = *b;5. *b = temp;6. }7.8. int partition(int *array, int low, int high)9. {10. int middle = (low+high)/2, temp, pivot,i,j;11.12.13. if (array[middle] < array[low])14. swap(&array[middle], &array[low]);15. if (array[high] < array[low])16. swap(&array[high], &array[low]);17. if (array[high] < array[middle])18. swap(&array[high], &array[middle]);19.20. pivot = array[middle];21.22. swap(&array[middle], &array[high-1]);23.24. for (i=low, j=high-1; ;) {25. while (array[++i]<pivot) {}26. while (pivot<array[--j]) {}27. if (i < j) {28. temp = array[j];29. array[j]=array[i];30. array[i]=temp;31. } else32. break;33. }34. swap(&array[i], &array[high-1]);35.36. return i;37. }给出一种比较简洁的写法:1. void Quick_Sort(int A[],int low,int high)2. {3. if(low<high)4. {5. int temp,t=A[low];6. int l=low,h=high;7. while(l<h)8. {9. while(A[l]<t) l++;10. while(A[h]>=t) h--;11. if(h>l)12. {13. temp=A[l];14. A[l]=A[h];15. A[h]=temp;16. }17. }18. Quick_Sort(A,low,l-1);19. Quick_Sort(A,l+1,high);20. }21. }四.归并排序归并排序是将两个或两个以上的有序子表合并成一个新的有序表。

相关文档
最新文档