交换排序-经典的冒泡排序算法总结
交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。
应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序。
时间复杂度O(n^2),
空间复杂度O(1)
稳定的排序算法
1、排序方法
将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。
(1)初始
R[1..n]为无序区。
(2)第一趟扫描
从无序区底部向上依次比较相邻的两个气泡的重量,若发现轻者在下、重者在上,则交换二者的位置。即依次比较(R[n],R[n-1]),(R[n-1],R[n-2]),…,(R[2],R[1]);对于每对气泡(R[j+1],R[j]),若R[j+1].key<R[j].key,则交换R[j+1]和R[j]的内容。
第一趟扫描完毕时,"最轻"的气泡就飘浮到该区间的顶部,即关键字最小的记录被放在最高位置R[1]上。
(3)第二趟扫描
扫描R[2..n]。扫描完毕时,"次轻"的气泡飘浮到R[2]的位置上……
最后,经过n-1 趟扫描可得到有序区R[1..n]
注意:
第i趟扫描时,R[1..i-1]和R[i..n]分别为当前的有序区和无序区。扫描仍是从无序区底部向上直至该区顶部。扫描完毕时,该区中最轻气泡飘浮到顶部位置R[i]上,结果是R[1..i]变为新的有序区。
2、冒泡排序过程示例
冒泡排序基本思想将n个记录看作按纵向排列,每趟排序时自下至上对每对相邻记录进行比较,若次序不符合要求(逆序)就交换。每趟排序结束时都能使排序范围内关键字最小的记录象一个气泡一样升到表上端的对应位置,整个排序过程共进行n-1趟,依次将关键字最小、次小、第三小…的各个记录“冒到”表的第一个、第二个、第三个… 位置上。
初态 第1趟 第2趟 第3趟 第4趟 第5趟 第6趟 第7趟
38 12 12 12 12 12 12 12
20 38 20 20 20 20 20 20
46 20 38 25 25 25 25 25
38 46 25 38 38 38 38 38
74 38 46 38 38 38 38 38
91 74 38 46 46 46 46 46
12 91 74 74 74 74 74 74
25 25 91 91 91 91 91 91
3、排序算法
(1)分析
因为每一趟排序都使有序区增加了一个气泡,在经过n-1趟排序之后,有序区中就有n-1个气泡,而无序区中气泡的重量总是大于等于有序区中气泡的重量,所以整个冒泡排序过程至多需要进行n-1趟排序。
若在某一趟排序中未发现气泡位置的交换,则说明待排序的无序区中所有气泡均满足轻者在上,重者在下的原则,因此,冒泡排序过程可在此趟排序后终止。为此,在下面给出的算法中,引入一个布尔量exchange,在每趟排序开始前,先将其置为FALSE。若排序过程中发生了交换,则将其置为TRUE。各趟排序结束时检查exchange,若未曾发生过交换则终止算法,不再进行下一趟排序。
(2)一般数据结构书上的具体算法伪代码
1: void BubbleSort(SeqList R)
2:
3: { //R(l..n)是待排序的文件,采用自下向上扫描,对R做冒泡排序
4:
5: int i,j;
6:
7: Boolean exchange; //交换标志
8:
9: for(i=1;i<n;i++){ //最多做n-1趟排序
10:
11: exchange=FALSE; //本趟排序开始前,交换标志应为假
12:
13: for(j=n-1;j>=i;j--) //对当前无序区R[i..n]自下向上扫描
14:
15: if(R[j+1].key<R[j].key){//交换记录
16:
17: R[0]=R[j+1]; //R[0]不是哨兵,仅做暂存单元
18:
19: R[j+1]=R[j];
20:
21: R[j]=R[0];
22:
23: exchange=TRUE; //发生了交换,故将交换标志置为真
24:
25: }
26:
27: if(!exchange) //本趟排序未发生交换,提前终止算法
28:
29: return;
30:
31: } //endfor(外循环)
32:
33: } //BubbleSort
具体实现:基本和上述伪代码吻合
1: void BubbleSort(int R[] ,int len)
2: { //R(0...n-1)是待排序的文件,采用自下向上扫描,对R做冒泡排序
3: int i =0, j=0;
4: int tmp =0;
5: bool exchange =false ; //交换标志
6: for(i=0;i< len-1 ; i++){ //最多做n-1趟排序
7: exchange= false ; //本趟排序开始前,交换标志应为假
8: for(j=len-2; j>=i; j--) //对当前无序区R[i..n-1]自下向上扫描
9: if(R[j+1] <R[j]){//交换记录
10: tmp =R[j+1];
11: R[j+1]=R[j];
12: R[j]=tmp ;
13: exchange=true ; //发生了交换,故将交换标志置为真
14: }
15: if(!exchange) //本趟排序未发生交换,提前终止算法
16: return ;
17: } //endfor(外循环)
18: } //BubbleSort
另一种从前往后扫描的算法,每一次扫描,最后面的数组排好序,源代码:
1: void bubble_sort_a(int R[] ,int len)
2: { //R(0...n-1)是待排序的文件,采用自下向上扫描,对R做冒泡排序
3: int i =0, j=0;
4: int tmp =0;
5: bool exchange =false ; //交换标志
6: for(i=0;i< len-1 ; i++){ //最多做n-1趟排序
7: exchange= false ; //本趟排序开始前,交换标志应为假
8: for(j=0; j< len-1 -i ; j++){ //对当前无序区R[0.. len-i-1]从前往后扫描
9: if(R[j+1] <R[j]){//交换记录
10: tmp =R[j+1];
11: R[j+1]=R[j];
12: R[j]=tmp ;
13: exchange=true ; //发生了交换,故将交换标志置为真
14: }
15: }
16: if(!exchange) //本趟排序未发生交换,提前终止算法
17: return ;
18: } //endfor(外循环)
19: } //BubbleSort_a
进一步分析发现,这样一种假设:
如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字,
那么在第一趟遍历后,最后发生交换的位置必定小于10,且这个位置之后的数据必定已经有序了,
记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。
参考来源:http://blog.csdn.net/morewindows/article/details/6657829
具体源代码:
1: void bubble_sort_b(int a[], int len)
2: {
3: int j, k;
4: int flag;
5: int tmp = 0;
6:
7: flag = len;
8: while (flag > 0)
9: {
10: k = flag;
11: flag = 0;
12: for (j = 1; j < k; j++)
13: if (a[j - 1] > a[j])
14: {
15: tmp =a[j -1];
16: a[j-1]=a[j];
17: a[j]=tmp ;
18: flag = j;
19: }
20: }
21: }
所有实例源代码(VS2010测试编译):
1: // code-summary.cpp : 定义控制台应用程序的入口点。
2:
3: /**************************************************************************
4: * Copyright (c) 2013, All rights reserved.
5: * 文件名称 : code-summary.cpp
6: * 文件标识 :
7: * 摘 要 : 冒泡排序算法
8: *
9: * 当前版本 : Ver 1.0
10: * 作者 : 徐冬冬
11: * 完成日期 : 2013/05/10
12: *
13: * 取代版本 :
14: * 原作者 :
15: * 完成日期 :
16: * 开放版权 : GNU General Public License GPLv3
17: *************************************************************************/
18: #include "stdafx.h"
19:
20: #include <iostream>
21: #include <random>
22: #include <stdlib.h>
23: using namespace std;
24:
25: //冒泡排序
26:
27: void init(int a[], int len)
28: {
29: int i =0;
30: for( i=0; i<len ;i++)
31: {
32: a[i]= rand();
33: }
34: return ;
35: }
36: void print(int *a, int len)
37: {
38: int i =0;
39: for( i=0; i<len; i++)
40: {
41: cout << a[i] <<'\t';
42: }
43: cout << endl;
44: return ;
45: }
46: void BubbleSort(int R[] ,int len)
47: { //R(0...n-1)是待排序的文件,采用自下向上扫描,对R做冒泡排序
48: int i =0, j=0;
49: int tmp =0;
50: bool exchange =false ; //交换标志
51: for(i=0;i< len-1 ; i++){ //最多做n-1趟排序
52: exchange= false ; //本趟排序开始前,交换标志应为假
53: for(j=len-2; j>=i; j--) //对当前无序区R[i..n-1]自下向上扫描
54: if(R[j+1] <R[j]){//交换记录
55: tmp =R[j+1];
56: R[j+1]=R[j];
57: R[j]=tmp ;
58: exchange=true ; //发生了交换,故将交换标志置为真
59: }
60: if(!exchange) //本趟排序未发生交换,提前终止算法
61: return ;
62: } //endfor(外循环)
63: } //BubbleSort
64:
65: void bubble_sort_a(int R[] ,int len)
66: { //R(0...n-1)是待排序的文件,采用自下向上扫描,对R做冒泡排序
67: int i =0, j=0;
68: int tmp =0;
69: bool exchange =false ; //交换标志
70: for(i=0;i< len-1 ; i++){ //最多做n-1趟排序
71: exchange= false ; //本趟排序开始前,交换标志应为假
72: for(j=0; j< len-1 -i ; j++){ //对当前无序区R[0.. len-i-1]从前往后扫描
73: if(R[j+1] <R[j]){//交换记录
74: tmp =R[j+1];
75: R[j+1]=R[j];
76: R[j]=tmp ;
77: exchange=true ; //发生了交换,故将交换标志置为真
78: }
79: }
80: if(!exchange) //本趟排序未发生交换,提前终止算法
81: return ;
82: } //endfor(外循环)
83: } //BubbleSort_a
84:
85: //冒泡排序3
86: /*
87: 分析优化,如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字,
88: 那么在第一趟遍历后,最后发生交换的位置必定小于10,且这个位置之后的数据必定已经有序了,
89: 记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。
90: */
91: void bubble_sort_b(int a[], int len)
92: {
93: int j, k;
94: int flag;
95: int tmp = 0;
96:
97: flag = len;
98: while (flag > 0)
99: {
100: k = flag;
101: flag = 0;
102: for (j = 1; j < k; j++)
103: if (a[j - 1] > a[j])
104: {
105: tmp =a[j -1];
106: a[j-1]=a[j];
107: a[j]=tmp ;
108: flag = j;
109: }
110: }
111: }
112:
113: int _tmain(int argc, _TCHAR* argv[])
114: {
115: int *arr = new int[10];
116: init(arr, 10);
117: print(arr, 10);
118: BubbleSort(arr,10);
119: print(arr, 10 );
120:
121: init(arr, 10);
122: print(arr, 10);
123: bubble_sort_a(arr,10);
124: print(arr, 10 );
125:
126: init(arr, 10);
127: print(arr, 10);
128: bubble_sort_b(arr,10);
129: print(arr, 10 );
130:
131: system("pause");
132: return 0;
133: }
134: