罗列各种排序Mark

那么,首先是我们所熟悉的各种排序的时间复杂度和空间复杂度


排序法

最差时间分析 平均时间复杂度 稳定度 空间复杂度
冒泡排序 O(n2) O(n2) 稳定 O(1)
快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n)
选择排序 O(n2) O(n2) 稳定 O(1)
二叉树排序 O(n2) O(n*log2n) 不一顶 O(n)

插入排序

O(n2) O(n2) 稳定 O(1)
堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1)
希尔排序 O O 不稳定 O(1)

接下来我们逐个排序算法来Mark。

一、冒泡排序

冒泡排序的定义:

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端,故名。
由于冒泡排序简洁的特点,它通常被用来对于计算机程序设计入门的学生介绍算法的概念。

冒泡排序的实现:

每一轮都是实现一下步骤直至排序完成

1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

3、针对所有的元素重复以上的步骤,除了最后一个。

4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较

冒泡排序的代码:

 1 static void sort(int[] a) {
 2         int temp = 0;
 3         boolean isSure;
 4         for (int i = a.length - 1; i > 0; --i) {
 5             isSure = true;
 6             for (int j = 0; j < i; ++j) {
 7                 if (a[j + 1] < a[j]) {
 8                     temp = a[j];
 9                     a[j] = a[j + 1];
10                     a[j + 1] = temp;
11                     isSure = false;
12                 }
13             }
14             if(isSure)
15                 break;
16         }
17     }

二、快速排序

快速排序的定义:

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序的实现:

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]赋给A[i];
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]赋给A[j];
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[j]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

快速排序的代码:

 1 public static void sort(int a[], int start, int end){
 2         int i,j;
 3         i = start;
 4         j = end;
 5         if((a==null)||(a.length==0))
 6                 return;
 7         while(i<j){
 8                 while(i<j&&a[i]<=a[j]){     //以数组start下标的数据为key,右侧扫描
 9                     j--;
10                 }
11                 if(i<j){                   //右侧扫描,找出第一个比key小的,交换位置
12                     int temp = a[i];
13                     a[i] = a[j];
14                     a[j] = temp;
15                 }
16                 while(i<j&&a[i]<a[j]){    //左侧扫描(此时a[j]中存储着key值)
17                     i++;
18                 }
19                 if(i<j){                 //找出第一个比key大的,交换位置
20                     int temp = a[i];
21                     a[i] = a[j];
22                     a[j] = temp;
23                 }
24         }
25         if(i-start>1){
26             //递归调用,把key前面的完成排序
27             sort(a,start,i-1);
28         }
29         if(end-i>1){
30             sort(a,i+1,end);    //递归调用,把key后面的完成排序
31         }
32     }

以下是快速排序的非递归实现

 1 static void method2(int[] nums){
 2         int[] marks = new int[nums.length*2];
 3         marks[0] = 0;
 4         marks[1] = nums.length -1;
 5         int a=0,b=1; //a为任务执行的标识,b为新增任务的标识
 6         int i=0,j=0;        //i和j作为任务执行中的上标和下标
 7         int temp;        //temp为临时交换时用的变量
 8         while(a<b){
 9             i = marks[2*a];
10             j = marks[2*a+1];
11             while(i<j){
12                 while(i<j&&nums[i]<=nums[j])
13                     j--;
14                 if(i<j){
15                     temp = nums[i];
16                     nums[i] = nums[j];
17                     nums[j] = temp;
18                 }
19                 while(i<j&&nums[i]<nums[j])
20                     i++;
21                 if(i<j){
22                     temp = nums[i];
23                     nums[i] = nums[j];
24                     nums[j] = temp;
25                 }
26             }
27             if(i-marks[2*a]>1){
28                 marks[2*b] = marks[2*a];
29                 marks[2*b+1] = i-1;
30                 b++;
31             }
32             if(marks[2*a+1]-i>1){
33                 marks[2*b] = i+1;
34                 marks[2*b+1] = marks[2*a+1];
35                 b++;
36             }
37             a++;
38         }
39         System.out.println(nums.length+":"+2*b);
40     }

三、选择排序

选择排序的定义:

每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

选择排序的实现:

对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。

选择排序的代码:

 1 public static void sort(int a[]){
 2         int i,j,tmp,b;
 3         for(i=0;i<a.length-1;i++)
 4         {
 5             tmp=i;
 6             for(j=i+1;j<a.length;j++)
 7                 if(a[tmp]>a[j])
 8             tmp=j;
 9             if(i!=tmp)
10             {
11                 b=a[tmp];
12                 a[tmp]=a[i];
13                 a[i]=b;
14             }
15         }
16     }

四、插入排序

插入排序的定义:

有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外,而第二部分就只包含这一个元素。在第一部分排序后,再把这个最后元素插入到此刻已是有序的第一部分里的位置

插入排序的实现:

⒈从有序数列和无序数列{a2,a3,…,an}开始进行排序;
⒉处理第i个元素时(i=2,3,…,n),数列{a1,a2,…,ai-1}是已有序的,而数列{ai,ai+1,…,an}是无序的。用ai与ai-1,a i-2,…,a1进行比较,找出合适的位置将ai插入;
⒊重复第二步,共进行n-i次插入处理,数列全部有序。

插入排序的代码:

 1 public static void insertSort(int[] a) {
 2         for (int index = 1; index < a.length; index++) {
 3             int subIndex = index;
 4             int currentData = a[index];
 5             while ((subIndex > 0) && (a[subIndex - 1] > currentData)) {
 6                 a[subIndex] = a[subIndex - 1];
 7                 subIndex--;
 8                 a[subIndex] = currentData;
 9             }
10         }
11     }

五、堆排序

堆排序的定义:

有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外,而第二部分就只包含这一个元素。在第一部分排序后,再把这个最后元素插入到此刻已是有序的第一部分里的位置

堆排序的实现:

⒈从有序数列和无序数列{a2,a3,…,an}开始进行排序;
⒉处理第i个元素时(i=2,3,…,n),数列{a1,a2,…,ai-1}是已有序的,而数列{ai,ai+1,…,an}是无序的。用ai与ai-1,a i-2,…,a1进行比较,找出合适的位置将ai插入;
⒊重复第二步,共进行n-i次插入处理,数列全部有序。

堆排序的代码:

 1 public static void sort(int[] heap){
 2         int temp;
 3         /*
 4         * 创建堆(对该堆进行简单的排序)
 5         */
 6         for (int i = heap.length - 1; i >= 0; i--) {
 7             AdjustHeap(heap,i,heap.length);
 8         }
 9         /*
10         * 排序
11         */
12         for (int i = heap.length - 1; 0 < i; i--) {
13             temp = heap[0];
14             heap[0] = heap[i];
15             heap[i] = temp;
16             /*
17             * 从堆顶进行调整,使未排序堆中最大关键字到堆顶
18             */
19             AdjustHeap(heap,0,i);
20         }
21     }
22
23
24     /*
25     * 调整堆使其堆顶为未排序堆中最大关键字
26     */
27     public static void AdjustHeap(int[] heap,int location,int unSortlength) {
28         int temp;
29         int tempLoc;
30         /*
31         * 确保左右节点存在
32         */
33         if ((tempLoc = (location + 1) * 2) < unSortlength) {
34         /*
35         * 判断左右节点大小
36         */
37         if (heap[tempLoc] >= heap[tempLoc - 1]) {
38             /*
39             * 判断父节点与子节点的大小,若父节点小,则与大的子节点换位
40             */
41             if (heap[location] < heap[tempLoc]) {
42                 temp = heap[location];
43                 heap[location] = heap[tempLoc];
44                 heap[tempLoc] = temp;
45                 /*
46                 *递归法对换位后的子节点及其子节点进行调整
47                 */
48                 AdjustHeap(heap,tempLoc,unSortlength);
49             }
50         } else {
51             /*
52             * 左节点大于右节点
53             */
54             if (heap[location] < heap[tempLoc - 1]) {
55                 temp = heap[location];
56                 heap[location] = heap[tempLoc - 1];
57                 heap[tempLoc - 1] = temp;
58                 /*
59                 * 递归法对换位后的子节点及其子节点进行调整
60                 */
61                 AdjustHeap(heap,tempLoc - 1,unSortlength);
62             }
63         }
64         }
65         /*
66         * 确保左节点存在
67         */
68         else if ((tempLoc = (location + 1) * 2 - 1) < unSortlength) {
69             /*
70             * 与左节点进行比较
71             */
72             if (heap[location] < heap[tempLoc]) {
73                 /*
74                 *左子节点大于父节点,将两者进行换位
75                 */
76                 temp = heap[location];
77                 heap[location] = heap[tempLoc];
78                 heap[tempLoc] = temp;
79                 AdjustHeap(heap,tempLoc,unSortlength);
80             }
81         }
82     }

六、希尔排序

希尔排序的定义:

希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。

希尔排序的实现:

希尔排序属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序。
排序过程:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序;然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止。

希尔排序的代码:

 1 static void ShellSort(int Index) {
 2         int j;
 3         int Temp; // 暂存变量
 4         int DataLength; // 分割集合的间隔长度
 5         int Pointer; // 进行处理的位置
 6         DataLength = (int) Index / 2; // 初始集合间隔长度
 7         while (DataLength != 0) // 数列仍可进行分割
 8         {
 9             // 对各个集合进行处理
10             for (j = DataLength; j < Index; j++) {
11                 Temp = a[j]; // 暂存Data[j]的值,待交换值时用
12                 Pointer = j - DataLength; // 计算进行处理的位置
13                 // 进行集合内数值的比较与交换值
14                 while (Pointer >= 0 && Pointer <= Index && Temp < a[Pointer]) {
15                     a[Pointer + DataLength] = a[Pointer];
16                     // 计算下一个欲进行处理的位置
17                     Pointer = Pointer - DataLength;
18                 }
19                 // 与最后的数值交换
20                 a[Pointer + DataLength] = Temp;
21             }
22             DataLength = DataLength / 2; // 计算下次分割的间隔长度
23         }
24     }

六、归并排序

归并排序的定义:

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。

归并排序的实现:【这里只说二路归并】

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。值得注意的是归并排序是一种稳定的排序方法。

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

图示:

时间: 2024-10-20 02:58:16

罗列各种排序Mark的相关文章

Html5 简单选择排序演示

简单选择排序,是选择排序算法的一种.基本思想:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止.由于在每次循环中,会对数值相等的元素改变位置,所以属于非稳定排序. --------------------------------------------------------------------- 如下图所示: 对简单选择排序的优化方案,是采用二元选择排序,即将其改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数.

Swift的排序算法总结

下面让我们一起来见识一下swift中基于Array的扩展的冒泡排序,选择排序和快速排序吧. 1.冒泡排序 冒泡排序再基础不过了,这里就不再讲其原理了,实在不会可以看下百度百科冒泡排序 既然冒泡排序避免不了数组中两个数据交换,先写一个交换函数 // 交换数组中i和j两个位置的数据 extension Array { fileprivate mutating func swap(i:Int,j:Int) { let temp = self[i] self[i] = self[j] self[j] =

ipad版简单美团界面功能实现(纯swift编写)

一 总体功能图一 : (ipad竖屏) 二 总体功能图二 : (ipad横屏) 三 讲解内容 1 搭建美团界面(掌握) 2 ios8.0之后的Popover的运用(重点) 3 协议(掌握) 4 通知(掌握) 5 细节处理 四 总体界面 1 由总体的app界面效果,能看出来,一个UIViewController控制器作为UINavigationController的根控制器就能满足条件. 五 导航条设置 1 自定义导航条 : (系统的导航条不能满足需求) 2 创建导航控制器类 3 获取全局的导航条

zoj 3870 异或运算

给你n个数   问有多少种情况  两两异或大于两个数中的最大值: 分析   如果a小于b    及大的为b  要想a^b大于b  及a的最高位(一定为1)与b的对应位不一样   及b的对应位为0  就一定满足   这样就转换为小的数的对应位 先排序   mark[i]表示i这个位置为0的数的个数 #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using

复习数据结构:排序算法(五)——快速排序的各种版本

之前已经比较熟悉快排的基本思想了,其实现的方式也有很多种.下面我们罗列一些常见的实现方式: 版本一:算法导论上的单向扫描,选取最后一个元素作为主元 #include<iostream> using namespace std; int partition(int data[], int low, int high) { int pivot = data[high]; // let the last atom be the pivot int i = low - 1; // mark the p

OC基础-NSArray排序

OC中的NSArray提供了较多的排序方法,可以对数组元素进行有效的排序,下面先准备一个Student和Course类来作为练习对象. 一 创建练习类 1 Course类 // Course.h #import <Foundation/Foundation.h> @interface Course : NSObject /** 初始化Course类的类方法*/ + (instancetype)courseWithEnglish:(float)englishRecords            

寒假集训日志(二)——最小生成树,拓扑排序,欧拉回路,连通路

今天学的内容挺多的. (一)首先说最小生成树,两种算法: 1.Kruskal算法( 将边排序,然后再选,关键在于检查是否连通,使用并查集) 2.Prim算法(使用点集,有点类似与最短路的算法) 第一题是并查集算法的使用: A - The Suspects Time Limit:1000MS     Memory Limit:20000KB     64bit IO Format:%I64d & %I64u Submit Status Description 严重急性呼吸系统综合症( SARS),

mysql中排序

排序(默认:asc升序; desc降序 如:根据成绩从高到低排序 select * from stu_info order by mark desc; 根据成绩从低到高排序 select * from stu_info order by mark asc;

数组的几种排序方式

// 1.使用NSComparator排序 { // 产生随机数 NSMutableArray *unsortDataM = [NSMutableArray array]; for (NSInteger index = 0; index < 20; index++) { int random = arc4random()%20; [unsortDataM addObject:@(random)]; } NSLog(@"使用NSComparator排序前的数据:%@",unsort