排序2

本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

h2.western { font-family: "Liberation Sans", sans-serif; font-size: 16pt }
h2.cjk { font-size: 16pt }
h2.ctl { font-size: 16pt }
h1 { margin-bottom: 0.21cm }
h1.western { font-family: "Liberation Sans", sans-serif; font-size: 18pt }
h1.cjk { font-family: "Noto Sans CJK SC Regular"; font-size: 18pt }
h1.ctl { font-family: "Noto Sans CJK SC Regular"; font-size: 18pt }
p { margin-bottom: 0.25cm; line-height: 120% }

排序2

1 快速排序

1.1 算法思想

快速排序的主要思想就是分而治之。选择一个主元,然后把原来的集合分为比主元小和比主元大两个子集合,然后递归的解决左边,递归的解决右边。我们使用一幅图片来进行说明

下面是快速排序的伪代码描述

void Quicksort( ElementType A[], int N )

{

if ( N < 2 ) return;

pivot = 从A[]中选一个主元;

将S = { A[] \ pivot } 分成2个独立子集:

A1={ a?S | a ? pivot } 和

A2={ a?S | a ? pivot };

A[] =

Quicksort(A1,N1)U

pivot}U

Quicksort(A2,N2);

}

1.2 快速排序的性能分析

因为快速排序是递归进行的,递归算法的好处体现在每次可以递归的解决规模差不多的子问题。如果主元选的不好,让子集大小很悬殊,那么快速排序就快不起来了。下面是使用一幅图片来说明如果主元选取的不好,那么就会很囧。

可以看出,如果主元选的不好,那么快速排序的时间复杂度为O(N^2),很糟糕

1.3
常见的选择主元的方法

1.随机取
pivot?rand()函数不便宜啊!

2.取头、中、尾的中位数

例如 8、12、3的中位数就是8

下面给出中位数法的伪代码描述

ElementType
Median3( ElementType A[], int Left, int Right )

{

int
Center = ( Left + Right ) / 2;

if
( A[ Left ] > A[ Center ] )

Swap(
&A[ Left ], &A[ Center ] );

if
( A[ Left ] > A[ Right ] )

Swap(
&A[ Left ], &A[ Right ] );

if
( A[ Center ] > A[ Right ] )

Swap(
&A[ Center ], &A[ Right ] );

/*
A[ Left ] <= A[ Center ] <= A[ Right ] */

Swap(
&A[ Center ], &A[ Right-1 ] ); /* 将pivot藏到右边
*/

/*
只需要考虑 A[
Left+1 ] ... A[ Right–2 ] */

return
A[ Right-1 ]; /* 返回 pivot
*/

}

1.4
子集划分算法

使用一幅图片来说明

如果有元素正好等于pivot怎么办?

1.停下来交换?

1.不理它,继续移动指针?

举一个极端的例子,如果,如果一个数组全是和主元相等,如果使用停下来交换,就会做无用的交换,如果
不理它,继续移动指针,那么i会一直移动到大于j,此时我们的主元就会在端点,那么所造成的影响就是时间复杂度为O(N^2)

所以我们选择 停下来交换

1.5快速排序的问题

1.用递归......

对小规模的数据(例如N不到100)可能还不如插入排序快

2.解决方案

当递归的数据规模充分小,则停止递归,直接调用简单排序(例如插入排序)

在程序中定义一个Cutoff的阈值
—— 课后去实践一下,比较不同的Cutoff对效率的影响

1.6快速排序的测试结果

阀值都取100的情况下

1.7
结果分析

对于不同的阀值,发现效率差距并不是很大。但是选择不同pivot,差距很大。从测试结果看

中位数效果最好,随机数次之,使用第一个元素作为pivot效果最差。所以今后尽量使用中位数方法。

1.8 快速排序代码

  1 /*
  2  * quickSort.c
  3  *
  4  *  Created on: 2017年5月20日
  5  *      Author: ygh
  6  */
  7
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #define  MAX_LENGTH 100000
 11 typedef int elementType;
 12
 13 /*
 14  * Swap two integer number value
 15  */
 16 void swap(elementType *a, elementType *b) {
 17     int temp = *b;
 18     *b = *a;
 19     *a = temp;
 20 }
 21
 22 /*
 23  * Print the array to console
 24  * @param a A integer array need to sort
 25  * @param n The length of the array
 26  */
 27 void printArray(int a[], int n) {
 28     int i;
 29     for (i = 0; i < n; i++) {
 30         if (i == n - 1) {
 31             printf("%d", a[i]);
 32         } else {
 33             printf("%d ", a[i]);
 34         }
 35     }
 36     printf("\n");
 37 }
 38
 39 /*
 40  * Get input data from command
 41  */
 42 void getInputData(elementType *a, int n) {
 43     int i;
 44     elementType x;
 45     for (i = 0; i < n; i++) {
 46         scanf("%d", &x);
 47         a[i] = x;
 48     }
 49 }
 50
 51 /*
 52  * Implement insertion sort.
 53  *@param a A <code>elementType</code> array need to sort
 54  *@param n The length of the array
 55  */
 56 void insertion_sort(elementType a[], int n) {
 57     int i, j;
 58     elementType temp;
 59     for (i = 1; i < n; i++) {
 60         temp = a[i];
 61         for (j = i; j > 0 && a[j - 1] > temp; j--) {
 62             a[j] = a[j - 1];
 63         }
 64         a[j] = temp;
 65     }
 66
 67 }
 68
 69 /*
 70  *Get the pivot by get the median amount three number
 71  */
 72 elementType getPivotByMedian3(elementType a[], int left, int right) {
 73     int center = (left + right) / 2;
 74     /*
 75      * Let a[left]<= a[center] <= a[right]
 76      */
 77     if (a[left] > a[center]) {
 78         swap(&a[left], &a[center]);
 79     }
 80
 81     if (a[left] > a[right]) {
 82         swap(&a[left], &a[right]);
 83     }
 84
 85     if (a[center] > a[right]) {
 86         swap(&a[center], &a[right]);
 87     }
 88
 89     /*
 90      * We has known the a[right] greater than a[center]
 91      * so we swap the a[center] and a[right-1],so we just
 92      * consider from a[left+1] to a[right-2] when we divide sub-set
 93      */
 94     swap(&a[center], &a[right - 1]);
 95     return a[right - 1];
 96
 97 }
 98
 99 elementType getPivotByRandom(elementType a[], int left, int right) {
100     int index = rand() % (right - left + 1) + left;
101     return index;
102 }
103
104 /*
105  * Implement quick sort,we get the pivot by the middle of three numbers
106  * @param a A <code>elementType</code> array need to sort
107  * @param left The starting index of sub-set
108  * @param right The finishing index of sub-set
109  * @param A cutoff to determine how many numbers rest we will
110  * use the insertion sort.
111  */
112 void qSort(elementType a[], int left, int right, int cutoff) {
113     int low, high;
114     elementType pivot;
115     if (cutoff <= right - left) {
116         pivot = getPivotByMedian3(a, left, right);
117         low = left;
118         high = right - 1;
119         while (1) {
120             while (a[++low] < pivot)
121                 ;
122             while (a[--high] > pivot)
123                 ;
124             if (low < high) {
125                 swap(&a[low], &a[high]);
126             } else {
127                 break;
128             }
129         }
130         swap(&a[low], &a[right - 1]);
131         qSort(a, left, low - 1, cutoff);
132         qSort(a, low + 1, right, cutoff);
133
134     } else {
135         insertion_sort(a + left, right - left + 1);
136     }
137 }
138
139 /*
140  * Implement quick sort,we get the pivot by the middle of three numbers
141  * @param a A <code>elementType</code> array need to sort
142  * @param left The starting index of sub-set
143  * @param right The finishing index of sub-set
144  * @param A cutoff to determine how many numbers rest we will
145  * use the insertion sort.
146  */
147 void qSortByRandom(elementType a[], int left, int right, int cutoff) {
148     int low, high, index;
149     elementType pivot;
150     if (cutoff <= right - left) {
151         index = getPivotByRandom(a, left, right);
152         swap(&a[left], &a[index]);
153         pivot = a[left];
154         low = left;
155         high = right;
156         while (low < high) {
157             while (low < high && a[high] >= pivot) {
158                 high--;
159             }
160             a[low] = a[high];
161             while (low < high && a[low] <= pivot) {
162                 low++;
163             }
164             a[high] = a[low];
165         }
166         a[low] = pivot;
167         qSortByRandom(a, left, low - 1, cutoff);
168         qSortByRandom(a, low + 1, right, cutoff);
169     } else {
170         insertion_sort(a + left, right - left + 1);
171     }
172 }
173
174 /*
175  * Implement quick sort,we get the pivot by the middle of three numbers
176  * @param a A <code>elementType</code> array need to sort
177  * @param left The starting index of sub-set
178  * @param right The finishing index of sub-set
179  * @param A cutoff to determine how many numbers rest we will
180  * use the insertion sort.
181  */
182 void qSortByFirstNum(elementType a[], int left, int right, int cutoff) {
183     int low, high;
184     elementType pivot;
185     if (cutoff <= right - left) {
186         pivot = a[left];
187         low = left;
188         high = right;
189         while (low < high) {
190             while (low < high && a[high] >= pivot) {
191                 high--;
192             }
193             a[low] = a[high];
194             while (low < high && a[low] <= pivot) {
195                 low++;
196             }
197             a[high] = a[low];
198         }
199         a[low] = pivot;
200         qSortByFirstNum(a, left, low - 1, cutoff);
201         qSortByFirstNum(a, low + 1, right, cutoff);
202     } else {
203         insertion_sort(a + left, right - left + 1);
204     }
205 }
206
207 /*
208  * Implement sort unitized interface
209  * @param a A <code>elementType</code> array need to sort
210  * @param n The length of the array
211  */
212 void quickSort(elementType a[], int n) {
213 //    qSort(a, 0, n - 1, 100);
214 //    qSortByRandom(a, 0, n - 1, 100);
215     qSortByFirstNum(a, 0, n - 1, 2);
216 }
217
218
219
220 int main() {
221     int a[MAX_LENGTH];
222     int n;
223     scanf("%d", &n);
224     getInputData(a, n);
225     quickSort(a, n);
226     printArray(a, n);
227     return 0;
228 }

quickSort

时间: 2024-10-13 10:46:18

排序2的相关文章

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

算法 希尔排序

希尔排序 Shell Sort 介绍: 希尔排序(Shell Sort)也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高. 执行流程: 首先

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

数字在排序数组中出现的次数

题目:统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 程序实现: import java.util.Scanner; public class Test38 { public static void main(String[] args) { /**  * 初始化数组,测试数据可以多种途径初始化  */   Scanner in = new Scanner(System.in); /*int[] a = 

算法 排序lowB三人组 冒泡排序 选择排序 插入排序

参考博客:基于python的七种经典排序算法   [经典排序算法][集锦]     经典排序算法及python实现 首先明确,算法的实质 是 列表排序.具体就是操作的列表,将无序列表变成有序列表! 一.排序的基本概念和分类 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法. 排序的稳定性: 经过某种排序后,如果两个记录序号同等,且两者在原无序记录中的先后秩序依然保持不变,则称所使用的排序方法是稳定的,反之是不稳定

C/C++算法竞赛入门经典Page11 例题1-5 三整数排序

题目:输入3个整数,从小到大排序后输出 样例输入: 20 7 33 样例输出: 7 20 33 首先,先声明三个整数a,b,c和一个临时变量t: int a,b,c,t;//1,b,c为三个整数,t为临时变量 输入三个整数: scanf("%d%d%d",&a,&b,&c); 进行3次if判断: 1.如果b>a,则a,b对调 2.如果c>a,则a,c对调 3.如果c>b,则b,c对调 代码: if(b>=a){ t=b; b=a; a=t

排序与查找

1.冒泡法排序 2.选择排序 3.二分法查找(有序数组) 4.无序数组(基本查找)

使用插件bootstrap-table实现表格记录的查询、分页、排序等处理

在业务系统开发中,对表格记录的查询.分页.排序等处理是非常常见的,在Web开发中,可以采用很多功能强大的插件来满足要求,且能极大的提高开发效率,本随笔介绍这个bootstrap-table是一款非常有名的开源表格插件,在很多项目中广泛的应用.Bootstrap-table插件提供了非常丰富的属性设置,可以实现查询.分页.排序.复选框.设置显示列.Card view视图.主从表显示.合并列.国际化处理等处理功能,而且该插件同时也提供了一些不错的扩展功能,如移动行.移动列位置等一些特殊的功能,插件可

AC日记——双栈排序 洛谷 P1155

双栈排序 思路: 二分图染+模拟: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1005 #define maxm 2000005 int n,head[maxn],E[maxm],V[maxm],cnt,col[maxn]; int minn[maxn],ai[maxn],sta1[maxn],sta2[maxn],top1,top2; bool if_[maxn][maxn]; inline void in(

输入password登录到主界面,录入学生编号,排序后输出

n 题目:输入password登录到主界面,录入学生编号,排序后输出 n 1.  语言和环境 A.实现语言 C语言 B.环境要求 VC++ 6.0 n 2.  要求 请编写一个C语言程序.将若干学生编号按字母顺序(由小到大)输出. 程序的功能要求例如以下: 1)  输入password"admin",正确则进入主界面,错误则直接推出(exit(0)): 2)从键盘输入5个学生编号"BJS1001","BJS2001"."BJS1011&