常用排序算法
考研复习数据结构时,总结的常用排序算法。
趁着开博之际记录一下,免得以后遗忘。哈哈哈~~~~
1 #ifndef _SORT_H
2 #define _SORT_H
3
4 /*
5 定义各种排序算法
6 */
7
8
9 /**************************************************************************************************************
10 功能:冒泡排序
11 参数:data为数据源,begin为开始序数,end为结束序数
12 原理:待排序的元素序列中的元素个数为n,从后向前两两比较元素大小,如果发生逆序,交换他们的位置
13 直至序列比较完。这是一趟冒泡排序,结果是将最小的元素交换到待排序序列的第一个位置,其余元素后挪。
14 下一趟排序前,确定最小的元素不再参加比较。如果一趟比较下来,没有发生交换,则认为序列顺序是正确的。
15 可以提前结束循环。这样下来,最多n-1趟比较,序列可以完成排序。
16 评价:时间复杂度为O(n*n),空间复杂度O(1),是一种稳定的算法。
17 由于移动了较多次元素,所以效率在简单排序中最低。
18 **************************************************************************************************************/
19 void BubbleSort(int *data,int begin,int end);
20
21
22 /**************************************************************************************************************
23 功能:快速排序
24 参数:data为数据源,begin为开始序数,end为结束序数
25 原理:任取待排序元素序列中的某个元素作为基准,按照该元素的大小,将序列分成2个子序列,左子序列都小于
26 该基准 ,右子序列都大于或等于该基准,该元素在2个序列的中间(即最终位置上)。对2个子序列各重复
27 上述动作,直至所有元素都到最终位置而止。
28 评价:平均时间为O(n*log2(n)),空间复杂度为O( log2(n) ),是一种不稳定的算法。
29 当原始序列基本有序时,性能最差,时间为O(n*n);但是就平均性能而言,性能最好。
30 **************************************************************************************************************/
31 void QuickSort(int *data,int begin,int end);
32
33
34 /**************************************************************************************************************
35 功能:完成快速排序的一趟排序,移动基准元素到其最终位置
36 参数:data为数据源,begin为开始序数,end为结束序数
37 返回:基准元素的最终位置
38 **************************************************************************************************************/
39 int QuickSortPartition(int *data,int begin,int end);
40
41
42 /**************************************************************************************************************
43 功能:直接插入排序
44 参数:data为数据源,begin为开始序数,end为结束序数
45 原理:把数组data[n]中待排序的n个元素分成有序表与无序表,开始时有序表只包含data[0]一个元素,无序表包含
46 其余元素。排序过程中将无序表中第一个元素插入到有序表中合适的位置。经过(n-1)次插入,无序表位空,
47 有序表包含n个元素。排序完成
48 评价:平均时间O(n*n),空间复杂O(1),是一种稳定的算法。当数组正序时,只需比较n-1次,无需移动;但当
49 数组逆序时,比较和移动次数均为达到O(n*n/2)。
50 **************************************************************************************************************/
51 void InsertSort(int *data,int begin,int end);
52
53
54 /**************************************************************************************************************
55 功能:折半插入排序
56 参数:data为数据源,begin为开始序数,end为结束序数
57 原理:与直接插入排序类似。区别,元素比较方式不同,利用折半查找的方法在有序表中找到合适的位置。
58 评价:平均时间O(n*n),空间复杂O(1),是一种稳定的算法。平均比较次数为O(n*log2(n))。
59 当n较大时,总比较次数比直接插入排序的最差情况好,但比后者的最好情况差。当数组基本有序时,
60 性能比直接插入排序差。
61 **************************************************************************************************************/
62 void BinaryInsertSort(int *data,int begin,int end);
63
64
65 /**************************************************************************************************************
66 功能:希尔排序
67 参数:data为数据源,begin为开始序数,end为结束序数
68 原理:与直接插入排序类似。设数组有n个元素,首先取gap=(n/3+1),以gap为间距,将全部元素分成gap个
69 子序列,即所有距离为gap的元素在同一个子序列。在每个子序列进行直接插入排序。然后缩小gap,
70 令gap=(gap/3+1),重复上述动作,直至gap<=1为止。当gap=1时,等价于直接插入排序。
71 评价:平均时间O(n^1.25~n^1.65),空间复杂O(1),是一种不稳定的算法。
72 由于开始时gap较大,每个子序列中元素比较少,排序比较快。待排序到后期时,子序列元素数量增多,
73 但由于前期工作的基础,使序列已基本有序,所以排序依然很快。
74 对于规模较大的序列(n<1000),希尔排序具有较高的效率,而且代码简单。
75 **************************************************************************************************************/
76 void ShellSort(int *data,int begin,int end);
77
78
79 /**************************************************************************************************************
80 功能:简单选择排序
81 参数:data为数据源,begin为开始序数,end为结束序数
82 原理:每一趟都从后面待排序的(n-i)个元素中选出最小的,作为有序表中的第i个元素。进行n-1趟之后,元素有序。
83 评价:平均时间O(n^2),空间复杂O(1),是一种不稳定的算法,移动次数不稳定。
84 元素的移动次数跟初始序列状态有关。当序列正序排列时,移动次数为0;但最坏情况下,每一趟都要移动元素,
85 总的移动次数为3*(n-1)。
86 **************************************************************************************************************/
87 void SelectSort(int *data,int begin,int end);
88
89
90 /**************************************************************************************************************
91 功能:堆排序
92 参数:data为数据源,begin为开始序数,end为结束序数
93 原理:一旦建立初始堆(大根堆),处于对顶的元素data[begin]就是该未排序序列最大的元素,将该元素与该序列
94 最后的元素交换,确定该该元素的最终位置。再对前面n-1个元素使用堆调整,使之重新成为堆。重复上述动作
95 直至无序表位空。
96 评价:平均时间O(n*log2(n)),空间复杂O(1),是一种不稳定的算法。适用于规模较大的排序。平均性能较
97 快速排序慢。
98 **************************************************************************************************************/
99 void HeapSort(int *data,int begin,int end);
100
101 /**************************************************************************************************************
102 功能:堆调整
103 参数:data为数据源,begin为开始序数,end为结束序数
104 原理:设定除data[begin]之外的元素均满足大根堆的定义,将该元素与其孩子比较,将较大的元素上移到父母的位置,
105 重复上述动作直至该元素大于其当前位置的孩子。
106 **************************************************************************************************************/
107 void HeapAdjust(int *data,int begin,int end);
108
109
110 /**************************************************************************************************************
111 功能:二路归并排序
112 参数:data为数据源,begin为开始序数,end为结束序数
113 原理:就是将2个有序表合并成一个新的有序表。该算法在执行时一直调用划分过程,直到子序列划分成一个空序列或
114 只有一个元素的序列,然后在归并过程中归并成长度为2的子序列,在归并为4的序列,依次类推,直至归并成
115 整个序列。此时 序列已经有序。 共调用(n*log2(n))次递归。
116 评价:最好,最差,平均时间复杂度为O(n^2),对序列的初始状态无关。空间复杂度为O(n),是一种稳定的算法。
117 **************************************************************************************************************/
118 void MergeSort(int *data,int begin,int end);
119
120 /**************************************************************************************************************
121 功能:合并序列
122 参数:data为数据源,begin为开始序数,mid为中间,分割2个子序列,end为结束序数
123 原理:将2个子序列(data[begin]~data[mid] 和 data[mid+1]~data[end])合并成一个有序数列,且2个子序列均
124 有序。
125 **************************************************************************************************************/
126 void Merge(int *data, int begin, int mid, int end);
127
128 #endif
1 #include "sort.h"
2 #include "util.h"
3
4 void BubbleSort(int *data,int begin,int end)
5 {
6 if(!data || begin<0 || end<0)
7 return ;
8
9 bool exchange=false;
10 int temp;
11 int i=0,j=0;
12
13 //正序排序
14 for(i=begin;i<end;i++)
15 {
16 exchange=false;
17 for(j=end;j>=i+1;j--) //从后向前扫描,将最小的元素前置
18 {
19 if(data[j-1]>data[j])
20 {
21 temp=data[j-1];
22 data[j-1]=data[j];
23 data[j]=temp;
24 exchange=true;
25 }
26 }
27
28 if(!exchange) //没有发生交换,数据顺序正确,跳出循环
29 return;
30 }//for
31 }
32
33 void QuickSort(int *data,int begin,int end)
34 {
35 if(begin<end && begin>=0)
36 {
37 int pivotPos=QuickSortPartition(data,begin,end);
38 QuickSort(data,begin,pivotPos-1);
39 QuickSort(data,pivotPos+1,end);
40 }
41 }
42
43 int QuickSortPartition(int *data,int begin,int end)
44 {
45 if(!data || begin<0 || end<0)
46 return -1 ;
47
48 int pivot=data[begin];
49 int i=begin, j=end;
50
51 while(i != j) //从数组两端交替的向中间扫描
52 {
53 while(i<j && data[j]>pivot)
54 j--;
55 if(i<j) //从右扫描,将比基值小的值移动到左边
56 data[i++]=data[j];
57
58 while(i<j && data[i]<=pivot)
59 i++;
60 if(i<j) //从左扫描,将比基值大的值移动到右边
61 data[j--]=data[i];
62 }
63 data[i]=pivot; //将基值移动打最终的位置上
64 return i;
65 }
66
67
68 void InsertSort(int *data,int begin,int end)
69 {
70 if(!data || begin<0 || end<0)
71 return ;
72
73 int temp;
74 int i,j;
75 for(i=begin+1;i<=end;i++)
76 {
77 if(data[i]<data[i-1])
78 {
79 temp=data[i];
80 j=i-1;
81 //开始在有序表查找合适的位置,在查找的同时移动元素
82 do{
83 data[j+1]=data[j];
84 j=j-1;
85 }while(j>=begin && temp<data[j]);
86
87 data[j+1]=temp;
88 }
89 }
90 }
91
92 void BinaryInsertSort(int *data,int begin,int end)
93 {
94 if(!data || begin<0 || end<0)
95 return ;
96
97 int temp;
98 int i,low,high,mid;
99 for(i=begin+1;i<=end;i++)
100 {
101 if(data[i]<data[i-1])
102 {
103 temp=data[i];
104 low=begin,high=i-1;
105 //查找当前值在有序表中合适的位置,最终位置为low所在
106 while(low<=high)
107 {
108 mid=(low+high)/2;
109 if(data[mid]>temp)
110 {
111 high=mid-1;
112 }else{
113 low=mid+1;
114 }
115 }
116 //移动元素,腾出位置
117 for(int j=i-1;j>=low;j--)
118 data[j+1]=data[j];
119 //插入当前值到最终位置
120 data[low]=temp;
121 }
122 }
123 }
124
125
126
127 void ShellSort(int *data,int begin,int end)
128 {
129 if(!data || begin<0 || end<0)
130 return ;
131
132 int i,j,temp;
133 int gap=end-begin+1; //比较间距
134
135 do{
136 gap=gap/3+1;
137 for( i=begin+gap; i<=end; i++)
138 {
139 if(data[i]<data[i-gap])
140 {
141 temp=data[i];
142 j=i-gap;
143 do{
144 data[j+gap]=data[j];
145 j-=gap;
146 }while(j>begin && data[j]>temp);
147 data[j+gap]=temp;
148 }
149 }
150 }while(gap>1);
151 }
152
153
154 void SelectSort(int *data,int begin,int end)
155 {
156 if(!data || begin<0 || end<0)
157 return ;
158
159 int i,j,temp,min;
160 for(i=begin;i<end;i++)
161 {
162 min=i;
163
164 //开始挑选最小的元素
165 for(j=i+1;j<=end;j++)
166 {
167 if(data[j]<data[min])
168 min=j;
169 }
170 //交换
171 if(i!=min)
172 {
173 temp=data[i];
174 data[i]=data[min];
175 data[min]=temp;
176 }
177 }
178 }
179
180
181 void HeapSort(int *data,int begin,int end)
182 {
183 if(!data || begin<0 || end<0)
184 return ;
185
186 int temp, length=end-begin+1;
187
188 //建立初始堆
189 for(int i=length/2; i>0; i-- )
190 HeapAdjust(data,i,end);
191
192 //排序,每次取出最大值,放置到有序表的第一个位置,然后调整堆
193 for( int j=end; j>begin; j-- )
194 {
195 temp=data[begin];
196 data[begin]=data[j];
197 data[j]=temp;
198 HeapAdjust(data,begin,j-1);
199 }
200 }
201
202 void HeapAdjust(int *data,int begin,int end)
203 {
204 if(!data || begin<0 || end<0)
205 return ;
206
207 //大根堆,设定除data[begin]之外的元素均满足大根堆的定义
208 int temp = data[begin];
209 for( int i=begin*2; i<=end; i*=2)
210 {
211 if(i<end && data[i]<data[i+1])
212 i+=1;
213
214 //检查节点是否到达最终位置
215 if(temp>=data[i])
216 break;
217
218 //调整堆,交换子孩子与父母的位置
219 data[begin]=data[i];
220 begin=i;
221 }
222 //将节点移动到最终位置上
223 data[begin]=temp;
224 }
225
226 void Merge(int *data, int begin, int mid, int end)
227 {
228 //将表1data[begin]~data[mid] 和表2data[mid+1]~data[end] 合并成一个有序表,设定表1,表2有序。
229
230 if(!data || begin<0 || mid<0 || end<0)
231 return;
232
233 //建立data的副本
234 int *temp=new int[end-begin+1];
235 for(int i=begin;i<=end;i++)
236 temp[i-begin]=data[i];
237
238 int s1=begin,s2=mid+1;
239 int j=begin;
240 while(s1<=mid && s2<=end)
241 {
242 if(temp[s1-begin]<=temp[s2-begin])
243 data[j++]=temp[s1++-begin];
244 else
245 data[j++]=temp[s2++-begin];
246 }
247
248 while(s1<=mid)
249 data[j++]=temp[s1++-begin];
250 while(s2<=end)
251 data[j++]=temp[s2++-begin];
252
253 //删除temp
254 delete temp;
255 }
256
257 void MergeSort(int *data,int begin,int end)
258 {
259 if(!data || begin<0 || end<0)
260 return ;
261
262 if(begin<end)
263 {
264 int mid=(begin+end)/2;
265 MergeSort(data,begin,mid);
266 MergeSort(data,mid+1,end);
267 Merge(data,begin,mid,end);
268 }
269 }

浙公网安备 33010602011771号