排序算法稳定性

常用算法(冒泡、插入、选择、快速)和二叉树详解

浪子不回头ぞ 提交于 2020-04-08 13:59:31
  同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。   计算机科学中,算法的 时间复杂度 是一个函数,它定量描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号(Order)表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无穷时的情况。 定义   在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。 算法复杂度   算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。(算法的复杂性体现在运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度)。 时间复杂度   1. 一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n),因此,算法的时间复杂度记做:T(n)=O(f(n)) 分析:随着模块n的增大,算法执行的时间的增长率和 f(n) 的增长率成正比,所以 f(n) 越小,算法的时间复杂度越低,算法的效率越高。   2.

常见排序方法

不问归期 提交于 2020-04-03 14:55:14
比较常用的排序方法(升序): 冒泡排序: 最常用的排序方法。大体思路就是每次选出一个最大值,第二次选出次大值,基本上就是两个for循环。 鸡尾酒排序 :冒泡排序方法的变种,鸡尾酒排序,待排序数组首先从0->n-1找出最大值,然后n-2->0找出最小值,然后再从1->n-2找次大值……依次类推……一个while循环,里面套两个for循环即可。 奇偶排序 :也是冒泡排序的变种。一个while循环,里面两个for循环,但是一个for循环从0开始,一个从1开始,每次加2,比较相邻两个数值大小。 快速排序 :是分之思想的一种体现。对于一个待排序队列,首先选择一个 基准 ,扫描数据,大于这个基准数据的元素放在右侧,小于的放在左侧,然后左侧和右侧的数据又是待排序队列,再分别选择基准……递归下去,知道全部都是有序的。 插入排序: 是一种比较直观的排序方法,从待排序队列中构建有序队列,把剩余的待排序数据插入到有序队列中。 希尔排序 :分步长排序法,对相隔步长的数据分别进行排序,然后减小步长,直至步长为1,主要可以减少数据的移动次数。 选择排序: 选择一个最大元素放入队尾,然后从剩余的元素中选择最大的放入队尾的前一位置,直到待排序数组中只有一个元素为止。 堆排序算法 :选择排序的一种,不停的构建大(小)顶堆,然后取出顶,得到有序序列。 归并排序 :也是典型的分治法思想的应用

归并排序基本原理及实现

陌路散爱 提交于 2020-03-28 04:29:09
一、归并(Merge) 1. 概念 将两个 有序数列 合并成一个有序数列,我们称之为 “归并”。 2. 算法思路及实现 设两个有序的子序列(相当于输入序列)放在同一序列中相邻的位置上:array[low..m],array[m + 1..high],先将它们合并到一个局部的暂存序列 temp (相当于输出序列)中,待合并完成后将 temp 复制回 array[low..high]中,从而完成排序。 在具体的合并过程中,设置 i,j 和 p 三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较 array[i] 和 array[j] 的关键字,取关键字较小(或较大)的记录复制到 temp[p] 中,然后将被复制记录的指针 i 或 j 加 1,以及指向复制位置的指针 p 加 1。重复这一过程直至两个输入的子序列有一个已全部复制完毕(不妨称其为空),此时将另一非空的子序列中剩余记录依次复制到 array 中即可。 c语言实现如下: void merge(int* array, int low, int mid, int high) { assert(array && low >= 0 && low <= mid && mid <= high); int* temp = (int*)malloc((high - low + 1) * sizeof(int)); if (!temp

排序算法:冒泡排序

一世执手 提交于 2020-03-27 13:31:21
什么是冒泡排序? 冒泡排序是一种最基础的交换排序,它就是把相邻的元素两两进行比较,根据大小来交换元素的位置,把较小的元素放在前面较大的元素放在后面,重复‘比较’‘交换’操作,最终实现数组有序的效果。 原理图如下: 实现步骤: (1) 比较相邻两个元素的大小,然后把较小的数放在前面,较大的数放在后面。 (2) 经过n-1次比较后,最大的那个元素会沉到数组中第n-1个的位置 (3) 如果n-1大于0,就继续重复1,2 否则排序完成。 时间复杂度: 该排序算法在最好情况下(元素是完全有序的)时间复杂度是O(n),最坏情况下(元素是完全逆序的)时间复杂度是O(n²)。 冒泡排序、选择排序、插入排序时间复杂度都是O(n²) 稳定性: 数组中相同的值,经过排序后位置不变表示该排序算法是稳定的,否则是不稳定的。冒泡排序和插入排序是稳定排序,选择排序是不稳定排序。 冒泡排序第一版: public static int[] bubbleSort(int[] arr) { for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = 0; temp = arr[j]; arr[j] = arr[j+1]; arr[j

八大排序算法总结

孤街浪徒 提交于 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 02:57:20
这几天笔试了好几次了,连续碰到一个关于常见排序算法稳定性判别的问题,往往还是多选,对于我以及和我一样拿不准的同学可不是一个能轻易下结论的题目,当 然如果你笔试之前已经记住了数据结构书上哪些是稳定的,哪些不是稳定的,做起来应该可以轻松搞定。本文是针对老是记不住这个或者想真正明白到底为什么是稳 定或者不稳定的人准备的。 首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。 其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就 是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换 的次数可能会少一些(个人感觉,没有证实)。 回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。 (1)冒泡排序 冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无 聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来

冒泡排序

自作多情 提交于 2020-03-26 01:42:44
冒泡排序,是指计算机的一种排序方法,它的时间复杂度为O(n^2),虽然不及堆排序、快速排序的O(nlogn,底数为2),但是有两个优点:1.“编程复杂度”很低,很容易写出代码;2.具有稳定性,这里的稳定性是指原序列中相同元素的相对顺序仍然保持到排序后的序列,而堆排序、快速排序均不具有稳定性。不过,一路、二路归并排序、不平衡二叉树排序的速度均比冒泡排序快,且具有稳定性,但速度不及堆排序、快速排序。冒泡排序是经过n-1趟子排序完成的,第i趟子排序从第1个数至第n-i个数,若第i个数比后一个数大(则升序,小则降序)则交换两数  冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。   由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升

八大排序算法概述

元气小坏坏 提交于 2020-03-26 01:24:33
综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法 常见排序算法的稳定性 收藏 排序算法的稳定性:若待排序的序列中,存在多个具有相同关键字的记录,经过排序, 这些记录的相对次序保持不变,则称该算法是稳定的;若经排序后,记录的相对 次序发生了改变,则称该算法是不稳定的。 稳定性的好处:排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,可以避免多余的比较; 回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。 (1)冒泡排序 冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。 (2)选择排序 选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了

Python常见的几种算法

人盡茶涼 提交于 2020-03-21 10:48:59
冒泡排序 冒泡排序 (英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 冒泡排序算法的运作如下: 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 针对所有的元素重复以上的步骤,除了最后一个。 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 冒泡排序的分析 交换过程图示(第一次): 那么我们需要进行n-1次冒泡过程,每次对应的比较次数如下图所示: def bubble_sort(alist): for j in range(len(alist)-1,0,-1): # j表示每次遍历需要比较的次数,是逐渐减小的 for i in range(j): if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] li = [54,26,93,17,77,31,44,55,20] bubble_sort(li) print(li) 时间复杂度