精华内容
下载资源
问答
  • 排序算法的优劣比较

    2018-03-20 20:22:23
    排序算法的优劣比较,经过比较不同的数据量,进行不同的排序后的时间比较。
  • 排序算法优劣

    2017-02-21 01:12:00
    对n较大的排序记录。一般的选择都是时间复杂度为O(nlog2n)的排序方法。 时间复杂度来说: (1)平方阶(O(n2))排序 各类简单排序:直接插入、直接选择和冒泡排序; (2)线性对数阶(O(nlog2n))排序 快速排序、堆排序和...

    对n较大的排序记录。一般的选择都是时间复杂度为O(nlog2n)的排序方法。


    时间复杂度来说:

    (1)平方阶(O(n2))排序
      各类简单排序:直接插入、直接选择和冒泡排序;
    (2)线性对数阶(O(nlog2n))排序
      快速排序、堆排序和归并排序;
    (3)O(n1+§))排序,§是介于0和1之间的常数。

    希尔排序
    (4)线性阶(O(n))排序
      基数排序,此外还有桶、箱排序。

    说明:

    当原表有序或基本有序时,直接插入排序和冒泡排序将大大减少比较次数和移动记录的次数,时间复杂度可降至O(n);

    而快速排序则相反,当原表基本有序时,将蜕化为冒泡排序,时间复杂度提高为O(n2);

    原表是否有序,对简单选择排序、堆排序、归并排序和基数排序的时间复杂度影响不大。


    稳定性:

    排序算法的稳定性:若待排序的序列中,存在多个具有相同关键字的记录,经过排序, 这些记录的相对次序保持不变,则称该算法是稳定的;若经排序后,记录的相对 次序发生了改变,则称该算法是不稳定的。
    稳定性的好处:排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,可以避免多余的比较;

    稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序

    不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序

     

    选择排序算法准则:

    每种排序算法都各有优缺点。因此,在实用时需根据不同情况适当选用,甚至可以将多种方法结合起来使用。

    选择排序算法的依据

    影响排序的因素有很多,平均时间复杂度低的算法并不一定就是最优的。相反,有时平均时间复杂度高的算法可能更适合某些特殊情况。同时,选择算法时还得考虑它的可读性,以利于软件的维护。一般而言,需要考虑的因素有以下四点:

    1.待排序的记录数目n的大小;

    2.记录本身数据量的大小,也就是记录中除关键字外的其他信息量的大小;

    3.关键字的结构及其分布情况;

    4.对排序稳定性的要求。

    设待排序元素的个数为n.

    1)当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。

    快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
    堆排序 : 如果内存空间允许且要求稳定性的,

    归并排序:它有一定数量的数据移动,所以我们可能过与插入排序组合,先获得一定长度的序列,然后再合并,在效率上将有所提高。

    2) 当n较大,内存空间允许,且要求稳定性 =》归并排序

    3)当n较小,可采用直接插入或直接选择排序。

    直接插入排序:当元素分布有序,直接插入排序将大大减少比较次数和移动记录的次数。

    直接选择排序 :元素分布有序,如果不要求稳定性,选择直接选择排序

    5)一般不使用或不直接使用传统的冒泡排序。

    6)基数排序
    它是一种稳定的排序算法,但有一定的局限性:
      1、关键字可分解。
      2、记录的关键字位数较少,如果密集更好
      3、如果是数字时,最好是无符号的,否则将增加相应的映射复杂度,可先将其正负分开排序。

    转载于:https://www.cnblogs.com/13224ACMer/p/6422264.html

    展开全文
  • 冒泡排序和快速排序优劣

    千次阅读 2019-10-23 21:01:39
    冒泡排序时间复杂度:O( n ^ 2 ),相比于快速排序慢 。 冒泡排序是稳定的,不会改变相同元素的相对顺序 。 快速排序时间复杂度:O( nlog2n ),比冒泡排序快 。 快速排序是不稳定的,会改变相同元素的相对顺序...

    冒泡排序时间复杂度:O( n ^ 2 ),相比于快速排序慢 。

    冒泡排序是稳定的,不会改变相同元素的相对顺序 。

    快速排序时间复杂度:O( nlog2n ),比冒泡排序快 。

    快速排序是不稳定的,会改变相同元素的相对顺序 。例如,以第一个基准排序时,首先将最后一个元素 a 移到了第一个分区的第一个位置上,改变了与第二个 a 的相对顺序 。

     

    展开全文
  • 排序算法太多了,但大体可以归结于三类,冒泡排序,插入排序,选择排序,那么如果分析一个算法呢,评价一个算法的优劣呢,可以从三方面入手,1.排序算法的执行效率,2,排序算法的内存消耗 3,排序算法的稳定性,下面咱们先从这...

    https://www.jianshu.com/p/9f724c880124

     

    最近听了王争老师的数据结构与算法之美,大有获益,特写此博客与大家分享.

    排序算法太多了,但大体可以归结于三类,冒泡排序,插入排序,选择排序,那么如果分析一个算法呢,评价一个算法的优劣呢,可以从三方面入手,1.排序算法的执行效率,2,排序算法的内存消耗 3,排序算法的稳定性,下面咱们先从这三方面来学会如何分析算法.

    一:排序算法的执行效率

    针对执行效率可以从以下几点来分析:

    1,最好情况,最坏情况,平均情况时间复杂度

    为什么要区分这三种时间复杂度呢?第一,有些排序算法会区分,为了好对比,所以我们最好都做一下区分.第二,对于要排序的数据,有的接近有序,有的完全无序。有序度不同的数据,对于排序的执行时间肯定是有影响的,我们要知道排序算法在不同数据下的性能表现。

    2,时间复杂度的系数,常数,低阶

    我们知道,时间复杂度反应的是数据规模 n 很大的时候的一个增长趋势,所以它表示的时候会忽略系数、常数、低阶.但是实际的软件开发中,我们排序的可能是 10 个、100 个.1000 个这样规模很小的数据,所以,在对同一阶时间复杂度的排序算法性能对比的时候,我们就要把系数、常数、低阶也考虑进来.

    3,比较次数和交换(或移动次数)

    基于比较的排序算法的执行过程,会涉及两种操作,一种是元素比较大小,另一种是元素交换或移动.所以我们在分析排序算法的执行效率的时候,比较次数和交换(或移动次数)也要考虑进

    二:排序算法的内存消耗

    算法的内存消耗可以通过空间复杂度来衡量,排序算法也是一样.不过针对排序算法的空间复杂度,我们还引入一个新的概念,原地排序.原地排序算法,就是特指空间复杂度是 O(1) 的排序算法,今天我们讲的三种算法,都是原地排序算法.

    三:排序算法的稳定性

    这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间的前后顺序不变.

    这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后就是 2,3,3,4,8,9。

    这组数据里有两个 3。经过某种排序算法排序之后,如果两个 3的前后顺序没有改变,我们就把这种排序算法叫稳定的排序算法.如果前后顺序发生改变,这种算法就是不稳定排序算法.

    但是这种稳定性对排序有什么影响呢?举个例子,比如说我们现在要给电商交易系统中的订单进行排序,要按照下单时间,和交易金额两个维度进行排序.我们希望按照金额从小到大排序,时间从早到晚排序,对于相同金额,按照从早到晚排序.

    最先想到的办法是:先按照订单金额进行排序,然后遍历排序好的数据,对于金额相同的小区间,按照时间从早到晚再排序.这种排序思路不难,但实行起来却不简单.

    借助稳定排序算法,这个问题可以非常简洁地解决.我们可以先按照订单时间 进行排序,排序完成后我们按照稳定排序算法再按照订单金额进行排序,两遍排序之后,我们的订单金额是按照从小到大进行排序,金额相同的是按照时间从早到晚进行排序.为什么呢?稳定排序算法可以保持金额相同的两个对象,在排序之后的前后顺序不变.

    下面开始学习这三种算法,先从冒泡算法开始吧!

    冒泡算法(Bubble sort)

    冒泡算法只会操作相邻的两个数据.冒泡算法每次都会对相邻的两个元素进行比较,看是否满足大小关系.如果不满足大小大小,就把他们的位置互换.一次冒泡,至少会让一个元素移动到他应该在的问题.重复了n次,就完成了 n个数据排序工作.举个例子,我们要对一组元素4,5,6,3,2,1按照从小到大进行排序.第一次冒泡操作的详细过程:

    可以看出,经过一次冒泡操作之后,6 这个元素已经存储在正确的位置,我们要完成所有数据的排序,就要经过6次这样的操作.

    当某次冒泡操作已经没有数据交换时,说明已经达到完全有序,不用进行后续操作,举个例子,这里有6个元素,只需要四个冒泡操作就可以.

    冒泡算法原理比较简单,下面我把代码贴出来:我用的oc语言

     

    现在咱们可以结合之前讲的分析排序算法来思考三个问题:

    1,冒泡算法是原地排序算法吗?

    冒泡的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,所以他的空间复杂度为O(1),是一个原地排序算法.

    2,冒泡算法是稳定的排序算法吗?

    为了保证冒泡算法的稳定系,当有相邻两个元素大小相等的时候,我们不做交换,所以冒泡算法是稳定的排序算法.

    3,冒泡排序的时间复杂度是多少?

    最好的情况,要排序的数据已经有序了,我们只进行一次冒泡操作,所以时间复杂度是O(n),最坏的情况是要排序的数据是倒序的,我们要进行n次冒泡操作,所以时间复杂度是O(n^2)

    那么平均复杂度怎样计算呢?平均时间复杂度就是加权平均期望时间复杂度,分析的时候要结合概率论.

    对于包含n个元素的数组,这n个元素就有n!(n的阶乘1*2*(n-2)*(n-1)*n)种排列方式 ,不同的排列方式,冒泡算法排序的时间也是不同的.比如我们前面举过的例子,其中一个要进行6次冒泡,另一个要4次,如果用概率论方法定量分析平均时间复杂度,涉及的数学推理和计算比较复杂,我们可以通过另一种思路,通过有序度逆序度来分析.

    有序度是数组中具有有序 关系的元素对的个数,有序元素对用数学表达式表示就是这样,

    有序元素对:a[i] <= a[j], 如果 i < j。

    对于一个倒序排列的数组的有序度是0, 如:6,5,4,3,2,1,对于一个正序排列数组1,2,3,4,5,6 有序度是n*(n-1)/2,也就是15,我们把这种完全有序的数组的有序度称为满有序度.

    逆序度的定位和有序度正好相反,逆序元素对:a[i] > a[j], 如果 i < j。

    这三个概念可以得到一个公式,逆序度=满有序度-有序度.

    比如前面那个冒泡算法的有序度对应关系就是:

    冒泡排序包含两个操作原子,比较和交换。每交换一次,有序度就加 1。不管算法怎么改进,交换次数总是确定的,即为逆序度,也就是n*(n-1)/2–初始有序度。此例中就是 15–3=12,要进行 12 次交换操作。

     

    插入排序(Insertion Sort)

    一个有序的数组,我们往里面插入一个元素,怎么保证数据有序呢?我们只需要遍历数组,找到数据应该插入的地方将其插入.

    具体怎么去做呢,首先我们把数组中的数据分为两个区间,已排序区间未排序区间.初始已排序区间只有一个元素,就是数组的第一个元素.插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。

    如图所示,要排序的数据是 4,5,6,1,3,2,其中左侧为已排序区间,右侧为未排序区间.

    插入排序也包含两种操作,一种是元素的比较,一种是元素的移动.当我们需要将一个数据 a 插入到已排序区间时,需要拿 a 与已排序区间的元素依次比较大小,找到合适的插入位置。找到插入点之后,我们还需要将插入点之后的元素顺序往后移动一位,这样才能腾出位置给元素 a 插入。

     对于不同的查找插入点方法(从头到尾、从尾到头),元素的比较次数是有区别的。但对于一个给定的初始序列,移动操作的次数总是固定的,就等于逆序度。

    为什么说移动次数就等于逆序度呢?我拿刚才的例子画了一个图表,你一看就明白了。满有序度是 n*(n-1)/2=15,初始序列的有序度是 5,所以逆序度是 10。插入排序中,数据移动的个数总和也等于 10=3+3+4。

     

    代码展示:oc代码

     

    大家也可以思考下那三个问题,1,插入排序是否是原地排序2,插入排序是否是稳定的排序,插入排序的时间复杂度.

    选择排序(Selection Sort)

     

    照例也是有三种算法需要你思考:前面已经有分析,这里直接公布结果:

    首先,选择排序空间复杂度为 O(1),是一种原地排序算法。选择排序的最好情况时间复杂度、最坏情况和平均情况时间复杂度都为 O(n2)。

    选择排序是不稳定的排序算法,从我前面画的那张图中,你可以看出来,选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。

    比如 5,8,5,2,9 这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素 2,与第一个 5 交换位置,那第一个 5 和中间的 5 顺序就变了,所以就不稳定了。正是因此,相对于冒泡排序和插入排序,选择排序就稍微逊色了。

    解答开头的问题

    冒泡排序和插入排序的时间复杂度都是 O(n2),都是原地排序,为什么插入排序要比冒泡排序更受欢迎呢?

    从代码实现上来看,冒泡排序的数据交换要比插入排序的数据移动要复杂的多,冒泡排序需要 3 个赋值操作,而插入排序只需要 1 个。

    我们来看这段操作:

    我们把执行一个赋值语句的时间粗略地计为单位时(unit_time),然后分别用冒泡排序和插入排序对同一个逆序度是 K 的数组进行排序.用冒泡排序,需要 K 次交换操作,每次需要 3 个赋值语句,所以交换操作总耗时就是 3*K 单位时间.而插入排序中数据移动操作只需要 K 个单位时间。

    内容总结

    要想分析、评价一个排序算法,需要从执行效率、内存消耗和稳定性三个方面来看。因此,这一节,我带你分析了三种时间复杂度是 O(n2) 的排序算法,冒泡排序、插入排序、选择排序。你需要重点掌握的是它们的分析方法。



    作者:我是码神
    链接:https://www.jianshu.com/p/9f724c880124
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • 各种排序算法及其优劣

    千次阅读 2017-04-22 20:36:44
    排序算法优劣的衡量标准 时间代价(最大时间代价,最小时间代价,平均时间代价):记录的移动和比较次数 空间代价,算法自身的复杂程度 1. 直接插入排序:空间代价O(1);时间代价O(n^2);该稳定排序。 int ...
    排序算法优劣的衡量标准
    时间代价(最大时间代价,最小时间代价,平均时间代价):记录的移动和比较次数

    空间代价,算法自身的复杂程度

    1. 直接插入排序:空间代价O(1);时间代价O(n^2);该稳定排序。

    int InsertSort(int arr[], int n)
    {
    	int temp = 0;
    	int j = 0;
    	for (int i = 1; i < n; i++)
    	{
    		temp = arr[i];   //待插入元素赋值给temp
    		j = i - 1;  //从当前位置往前寻找i的正确位置
    		while (j >= 0 && arr[j]>temp)
    		{
    			arr[j + 1] = arr[j];
    			i--;
    		}
    		arr[i + 1] = temp;
    	}
    	return 0;
    }



    2. 折半插入排序:用二分法查找第i个记录的正确位置元素预先有序,时间复杂度O(n^2),该排序算法稳定。

    int biInsertSort(int arr[], int n)
    {
    	int left = 0, right = 0, mid = 0;
    	int p = 0;
    int ShellSort(int arr[], int n)
    {
    	int d = n / 2;   //增量为数组大小的一半
    	while (d >= 1)
    	{
    		for (int k = 0; k < d; k++)
    		{
    			for (int i = k + d; i < n; i += d)
    			{
    				int temp = arr[i];
    				int j = i - d;
    				while (j >= k&&arr[j]>temp)
    				{
    					arr[j + d] = arr[j];
    					j -= d;
    				}
    				arr[j + d] = temp;
    			}
    		}
    		d = d / 2;
    	}
    	return 0;
    }
    

    for (p = 1; p < n; p++){int temp = arr[p]; //保存待插入数据left = 0;right = p - 1;while (left <= right){mid = (left + right) / 2;if (arr[mid]>temp)right = mid - 1;elseleft = mid + 1;}for (int i = p - 1; i >= left; i--)arr[i + 1] = arr[i];arr[left] = temp;}return 0;}
    
    


    3. 希尔排序:先将序列转化为若干小序列,在小序列内进行插入排序,然后逐渐扩大小序列的规模
    减少序列个数,最终对整个序列进行插入排序完成排序
    不稳定,空间代价:O(1);时间代价O(n)到O(n^2),视增量序列而定

    int ShellSort(int arr[], int n)
    {
    	int d = n / 2;   //增量为数组大小的一半
    	while (d >= 1)
    	{
    		for (int k = 0; k < d; k++)
    		{
    			for (int i = k + d; i < n; i += d)
    			{
    				int temp = arr[i];
    				int j = i - d;
    				while (j >= k&&arr[j]>temp)
    				{
    					arr[j + d] = arr[j];
    					j -= d;
    				}
    				arr[j + d] = temp;
    			}
    		}
    		d = d / 2;
    	}
    	return 0;
    }
    

    4. 改进的冒泡排序
    稳定性:稳定   空间代价分析:O(1)  时间代价分析:O(n^2)

    int BubbleSort(int arr[], int n)
    {
    	int flag = 0;   //标记每一趟排序过程中是否发生了交换
    	for (int i = 0; i < n; i++)
    	{
    		flag = 0;
    		for (int j = 0;j < n - i; j++)
    		{
    			if (arr[j] < arr[j - 1])
    			{
    				flag = 1;
    				int temp = arr[j];
    				arr[j] = arr[j - 1];
    				arr[j - 1] = temp;
    			}
    		}
    		if (flag == 0)
    			return 0;
    	}
    	return 0;
    }


    5. 快速排序(分治法)
    平均时间空间代价均为:O(log(n))

    int Partition(int arr[], int left, int right)
    {
    	int pivot = arr[left];   //选择最左边的为轴元素
    	while (left < right)
    	{
    		while (left<right&&arr[right]>pivot)
    			right--;
    		arr[left] = arr[right];
    		while (left<right&&arr[left]<=pivot)
    			left++;
    		arr[right] = arr[left];
    	}
    	arr[left] = pivot;
    	return left;
    }
    void QuickSort(int arr[], int left, int right)
    {
    	if (left < right)
    	{
    		int p = Partition(arr, left, right);
    		QuickSort(arr, left, p - 1);
    		QuickSort(arr, p + 1, right);
    	}
    }


    6. 选择排序

    int SelectionSort(int arr[], int n)
    {
    for (int i = 1; i < n; i++)
    {
    int k = i - 1;
    for (int j = i; j < n; j++)
    {
    if (arr[j] < arr[j])
    k = j;
    }
    if (k != i - 1)
    {
    int t = arr[k];
    arr[k] = arr[i - 1];
    arr[i - 1] = t;
    }
    }
    return 0;
    }


    展开全文
  • 算法思路,排序优劣
  • 直接上图–各种排序算法的性能表 由表中数据可以得出的结论 (1):简单的说,所有相等的元素在经过某种排序后依然能够保持排序之前的相对次序,那么就称这种排序是稳定的。上述稳定的排序算法有:直接插入排序,...
  • 如何判断不同的排序算法的优劣呢? 衡量一个排序算法的优劣,我们主要会从以下 3 个角度进行分析: 时间复杂度,具体包括,最好时间复杂度、最坏时间复杂度以及平均时间复杂度。 空间复杂度,如果空间复杂度为 1...
  • 八种常见排序算法 1、选择排序:每趟从待排序的记录序列中选择关键字最小的记录放置到已排序表的最前位置,直到全部排完。 2、直接插入排序:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排好顺序的,现在...
  • 分析排序算法的优劣

    千次阅读 2012-11-02 22:38:48
    一 按平均时间将排序分为四类:  (1) 平方阶(O(n2))排序:冒泡,插入,选择.  (2) 线性对数阶(O(nlgn))排序:快速,归并,堆.  (3) O(n1+£)阶排序, £是介于0和1之间的常数,即0  (4) 线性阶(O(n))排序: ...
  • 1. 冒泡排序 冒泡排序是最简单的排序之一了,其大体思想就是通过与相邻元素的比较和交换来把小的数交换到最前面。这个过程类似于水泡向上升一样,因此而得名。举个栗子,...
  • 数据库排序一般要比在应用中排序速度快些 因为有针对的一些数据预处理 数据库中排序 需要考虑数据完整性 排序会占用查询性能 而在应用中处理不存在这个问题 数据库比应用更容易触到性能瓶颈 应用扩展易于数据库...
  • 各种排序算法详解及优劣对比

    千次阅读 2019-04-12 15:17:39
    插入排序,顾名思义就是基本操作是插入,不断把一个个元素插入一个序列中,最终得到排序序列。插入过程中需要一个个的处理未排序元素,最简单的方法就是按下标处理。处理一个元素时留下一个空...
  • 学习排序算法感觉有种回到高中做数学题的感觉,需要深入的理解这些排序算法,才能真正的掌握它。 如何评价、分析一个排序算法? 一)、排序算法的执行效率 如何来评估排序算法的执行效率呢 1、最好情况、最坏...
  • 理解希尔排序排序过程

    万次阅读 多人点赞 2018-01-30 09:41:06
    1,有关插入排序 (1)插入排序的基本方法是:每步将一个待排序的元素,按其排序码大小插入到前面已经排好序的一组元素的适当位置上去,直到元素全部插入为止。 (2)可以选择不同的方法在已经排好序的有序数据表...
  • 各种排序算法的优劣

    千次阅读 2010-11-07 13:44:00
       各种排序优缺点  文章分类:综合技术  转载程序人生 2010-04-24 23:25:20  一、冒泡排序  已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与a[2]...
  • 转载于:https://www.cnblogs.com/xiaochige/p/8343859.html
  • *算法优劣分析: * 时间复杂度 * 最好情况:O(n*log n) 最坏情况:O(n的平方) 平均情况:O(n*log n) * 空间复杂度 * O(n*log n) * 稳定性 * 不稳定 * * 在初始序列按照关键码有序或者基本有序时,蜕化为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,241
精华内容 9,296
关键字:

优劣排序