1 #include<iostream>
2 using namespace std;
3 void swap(int &i,int &j)//实现i,j交换的函数
4 {
5 i=i^j;
6 j=i^j;
7 i=i^j;
8 }
9 void Display(const int *arr,int length)
10 {
11 if(arr==NULL || length<=0)
12 {
13 return ;
14 }
15 int i;
16 for(i=0;i<length;i++)
17 {
18 cout<<arr[i]<<" ";
19 }
20 cout<<endl;
21 }
22 ////////////////////直接插入排序//////////////////
23 void InsertSort(int *arr,int length)//直接插入排序
24 {
25 if(arr==NULL || length<=1)//如果大小为1也无需再排序
26 {
27 return ;
28 }
29 int i;
30 for(i=1;i<length;i++)//从第二个值开始插
31 {
32 int temp=arr[i];//先保存待插入的值,因为移动会被覆盖
33 int j;
34 for(j=i-1;j>=0 && arr[j]>temp;j--)//一边比较一边移动
35 {
36 arr[j+1]=arr[j];
37 }
38 if(i!=j+1)//如果前面存在比a[i]小的数
39 {
40 arr[j+1]=temp;//在当前值的下一个位置插入
41 }
42 }
43 }
44
45 ///////////////////冒泡排序////////////////////////////
46 void BubbleSort(int *arr,int length)//冒泡排序
47 {
48 if(arr==NULL || length<=1)
49 {
50 return ;
51 }
52 int i,j;
53 bool change=true;//对冒泡排序的优化
54 for(i=0;i<length-1 && change;i++)//i表示最多冒泡的次数
55 {
56 change=false;
57 for(j=0;j<length-1-i;j++)
58 {
59 if(arr[j]>arr[j+1])//通过异或实现高效数据交换
60 {
61 swap(arr[j],arr[j+1]);
62 change=true;
63 }
64 }
65 }
66 }
67
68 /////////////////简单选择排序//////////////////////////
69 void SelectSort(int *arr,int length)//简单选择排序
70 {
71 if(arr==NULL || length<=1)
72 {
73 return ;
74 }
75 int i,min;
76 for(i=0;i<length-1;i++)
77 {
78 min=i;//每次假设第一个值为最小值
79 int j;
80 for(j=i+1;j<length;j++)
81 {
82 if(arr[min]>arr[j])
83 {
84 min=j;//记下当前最小值的位置
85 }
86 }
87 if(min!=i)
88 {
89 swap(arr[i],arr[min]);
90 }
91 }
92 }
93 ////////////////快速排序////////////////////////////////////
94 int Partition(int *arr,int left,int right)//将数组一分为二,并寻找支点的位置
95 {
96 int x=arr[left];//每次将第一个值作为支点的值
97 while(left<right)
98 {
99 while(arr[right]>=x && left<right)//从右向左扫描,注意是小于等于
100 {
101 right--;
102 }
103 if(left<right)
104 {
105 swap(arr[left],arr[right]);
106 }
107
108 while(arr[left]<=x && left<right)//从左向右扫描,注意是小于等于
109 {
110 left++;
111 }
112 if(left<right)
113 {
114 swap(arr[left],arr[right]);
115 }
116 }
117 return left;//此时left等于right
118 }
119
120 void QSort(int *arr,int left,int right)//快速排序,left=0,right=length-1
121 {
122 if(left<right)
123 {
124 int mid=Partition(arr,left,right);
125 QSort(arr,left,mid-1);
126 QSort(arr,mid+1,right);
127 }
128 }
129
130 void QuickSort(int *arr,int length)
131 {
132 if(arr==NULL || length<=1)
133 {
134 return ;
135 }
136 QSort(arr,0,length-1);
137 }
138
139 //////////////////////////归并排序/////////////////////////////////////
140 void Merge(int *arr,int first,int mid,int last,int *temp)//将arr[first...mid]与arr[mid+1...last]归并
141 {
142 int i,j;
143 int k=0;
144 for(i=first,j=mid+1;i<=mid && j<=last;)
145 {
146 if(arr[i]<=arr[j])//所以是稳定排序
147 {
148 temp[k++]=arr[i++];
149 }
150 else
151 {
152 temp[k++]=arr[j++];
153 }
154 }
155 while(i<=mid)
156 {
157 temp[k++]=arr[i++];
158 }
159 while(j<=last)
160 {
161 temp[k++]=arr[j++];
162 }
163 for(i=0;i<k;i++)//将合并后的数组temp[]还原到arr[]
164 {
165 arr[first+i]=temp[i];//是arr[low+i]不是arr[i]
166 }
167 }
168 void Msort(int *arr,int first,int last,int *temp)
169 {
170 if(first==last)
171 {
172 temp[first]=arr[first];
173 }
174 else if(first<last)
175 {
176 int mid=(first+last)/2;
177 Msort(arr,first,mid,temp);
178 Msort(arr,mid+1,last,temp);
179 Merge(arr,first,mid,last,temp);
180 }
181 }
182 void MergeSort(int *arr,int length)//归并排序
183 {
184 if(arr==NULL || length<=1)
185 {
186 return ;
187 }
188 int *temp=new int [length];
189 Msort(arr,0,length-1,temp);
190 delete []temp;
191 }
192
193 //////////////////希尔排序////////////////////////
194 void ShellInsert(int *arr,int length,int d)
195 {
196 int i,j;
197 for(i=d;i<length;i++)
198 {
199 int temp=arr[i];
200 for(j=i-d;j>=0 && arr[j]>temp;j-=d)
201 {
202 arr[j+d]=arr[j];
203 }
204 if(j!=i-d)
205 {
206 arr[j+d]=temp;
207 }
208 }
209 }
210
211 void ShellSort(int *arr,int length)//希尔排序
212 {
213 if(arr==NULL || length<=1)
214 {
215 return ;
216 }
217 int d=length/2;
218 while(d>=1)
219 {
220 ShellInsert(arr,length,d);
221 d/=2;
222 }
223 }
224
225 ////////////////堆排序(大顶堆)//////////////////////////
226 ///////堆是一个完全二叉树,若结点索引从0开始,则i结点的左孩子为2*i+1,右为2*i+2
227 void HeapAdjustDown(int *arr,int length,int i)//对第i个值做向下调整,i=0,...,length-1
228 {
229 if(arr==NULL || length<=0 || i<0)
230 {
231 return ;
232 }
233 int temp=arr[i];
234 int j;//i相当于前驱,j相当于后继
235 for(j=2*i+1;j<length;)//即j<=length-1
236 {
237 if(j+1<length && arr[j]<arr[j+1])//如果存在右孩子,且右孩子值待遇
238 {
239 j++;//与右孩子交换
240 }
241 if(arr[j]<=temp)//如果左右孩子中的较大值小于该结点值,则说明无需向下调整了
242 {
243 break;
244 }
245 else//如果左右孩子中的较大值大于该结点值,则想到直接插入排序
246 {
247 arr[i]=arr[j];//孩子结点值中较大的上移动
248 i=j;//i用于追踪待插入点的位置
249 j=2*i+1;
250 }
251 }
252 if(arr[i]!=temp)//如果i的值发生了移动
253 {
254 arr[i]=temp;//将最初第i个节点值放入合适的位置
255 }
256
257 }
258 void CreateHeap(int *arr,int length)//创建一个堆
259 {
260 if(arr==NULL || length<=0)
261 {
262 return ;
263 }
264 int i;
265 for(i=(length-2)/2;i>=0;i--)//最后一个元素的序号为length-1,故该结点的父结点为(length-2)/2
266 {
267 HeapAdjustDown(arr,length,i);//从倒数第二行开始倒着向下调整
268 }
269 }
270 void HeapDelete(int *arr,int len)//删堆顶元素,len表示当前表的长度
271 {
272 if(arr==NULL || len<=0 || len==1)//len=1,表示当堆中只有一个元素时,无需排序
273 {
274 return ;
275 }
276 else
277 {
278 swap(arr[0],arr[len-1]);
279 HeapAdjustDown(arr,len-1,0);//删除后,数组长度减1了
280 }
281 }
282
283 void HeapSort(int *arr,int length)//堆排序
284 {
285 if(arr==NULL || length<=1)
286 {
287 return ;
288 }
289 CreateHeap(arr,length);//先创建一个堆0
290 int i;
291 for(i=0;i<=length-1;i++)//删除length-1次即可,因为最后一个元素就剩自己了
292 {
293 HeapDelete(arr,length-i);
294 }
295 }
296 int main()
297 {
298 int a[]={2,6,3,1,4,5,1,21,12,3};
299 Display(a,sizeof(a)/sizeof(int));//显示排序前的元素
300 //void (*pSort)(int*,int)=NULL;//定义一个函数指针,方法一
301 typedef void (*Fun)(int *,int);//Fun为函数指针类
302 Fun pSort=NULL;//定义函数指针,方法二,与上面等价
303 // pSort=InsertSort;
304 // pSort=BubbleSort;
305 // pSort=SelectSort;
306 // pSort=QuickSort;
307 // pSort=ShellSort;
308 pSort=HeapSort;
309 if(pSort)
310 {
311 pSort(a,sizeof(a)/sizeof(int));//显示排序后的元素
312 }
313 Display(a,sizeof(a)/sizeof(int));
314 return 0;
315 }