7-12 排序 (25分)

冒泡排序

外层循环N-1次,内循环每两个相邻的数相比较,如果前面的比后面大,二者交换。每一次外循环的结果是前N-i个数中最大的数放第N-i个位置(下标N-i-1)。将N-1个数处理完后,剩下的一个数自然在第一个位置,不需要处理,所以是N-1次外循环。

时间复杂度:

最坏:O(N^2)

最好:O(N)

 1 void bubble_sort(long int a[])
 2 {
 3     for (int i = 0; i < N-1; i++)
 4     {    
 5         int flag=0;
 6         for (int j = 0; j < N-i-1; j++)
 7         {
 8             if (a[j] > a[j + 1])
 9             {
10                 flag =1;
11                 long int temp = a[j];
12                 a[j] = a[j + 1];
13                 a[j + 1] = temp;
14             }
15         }
16         if(flag == 0) break;
17     }
18 }

插入排序:

把当前数前面比当前数大的往后移动一位,再把当前数填到移出的空位中。

时间复杂度:

最坏:O(N^2)

最好:O(N)

 1 void Insert_sort(elemtype a[], int n )
 2 {
 3     for (int i = 1; i < n; i++)
 4     {
 5         int j;
 6         elemtype tmp = a[i];
 7         for (j = i; j > 0 && tmp < a[j - 1]; j--)
 8         {
 9             a[j] = a[j - 1];
10         }
11         a[j] = tmp;
12     }
13 }

选择排序:

每次循环在无序序列中选一个最小的放到有序序列(的最后一个位置)中。

时间复杂度:

θ(n^2)

 1 void selection_sort(elemtype a[], int n)
 2 {
 3     for(int i=0;i<n-1;i++)
 4     {
 5         int min = i;
 6         for(int j=i;j<n;j++)
 7         {
 8             if(a[j] < a[min])
 9             min = j;
10         }
11         if(min != i)
12         {
13             int tmp = a[i];
14             a[i] = a[min];
15             a[min] = tmp;
16         }
17     }
18 }

希尔排序:

间隔为increment的元素相互比较排序,increment的值每次循环减半(或其他)。

时间复杂度:

最坏:θ(n^2)

可选其他增量,进一步优化。

 1 void Shell_sort(elemtype a[])
 2 {
 3     int k;
 4     int Increment;
 5     for (Increment = N / 2; Increment >= 1; Increment /= 2)
 6     {
 7         for (int j = Increment; j < N; j++)
 8         {
 9             int tmp = a[j];
10             for (k = j; k - Increment >= 0; k -= Increment)
11             {
12                 if (tmp < a[k - Increment])
13                 {
14                     a[k] = a[k - Increment];
15                 }
16                 else break;
17             }
18             a[k] = tmp;
19         }
20     }
21 }

归并排序:

分而治之,使用递归将小序列排序再合并成大序列,再排序,再合并成更大序列,直至完成所有元素的排序。

时间复杂度:

O(NlogN)

额外空间复杂度:

O(N)

 1 void merge(elemtype a[], elemtype tmp[], int L, int R, int RE)
 2 {
 3     int LE = R - 1;
 4     int num = RE - L + 1;
 5     int L2 = L;
 6     while (L <= LE && R <= RE)
 7     {
 8         if (a[L] <= a[R])
 9         {
10             tmp[L2++] = a[L++];
11         }
12         else if (a[R] < a[L])
13         {
14             tmp[L2++] = a[R++];
15         }
16     }
17     while (L <= LE)
18     {
19         tmp[L2++] = a[L++];
20     }
21     while (R <= RE)
22     {
23         tmp[L2++] = a[R++];
24     }
25     for (int i = 0; i < num; i++, RE--)
26     {
27         a[RE] = tmp[RE];
28     }
29 }
30 
31 void Msort(elemtype a[], elemtype tmp[], int L, int R)
32 {
33     int C;
34     if (L < R)
35     {
36         C = (L + R) / 2;
37         Msort(a, tmp, L, C);
38         Msort(a, tmp, C + 1, R);
39         merge(a, tmp, L, C + 1, R);
40     }
41 }
42 
43 void Merge_sort(elemtype a[])
44 {
45     elemtype* tmp = new elemtype[N * sizeof(elemtype)];
46     if (NULL == tmp)
47     {
48         cerr << "error" << endl;
49         return;
50     }
51     else
52     {
53         Msort(a, tmp, 0, N - 1);
54         delete[]tmp;
55     }
56 }

快速排序:median3()选中枢元,以中枢元为界,比中枢元小的放左边,比中枢元大的放右边,再分别递归处理左右。

时间复杂度:

平均:O(NlogN)

最坏:O(N^2),当中枢元是边界值

额外空间复杂度:

O(logN)(递归)

 1 elemtype median3(elemtype a[], int L, int R)
 2 {
 3     int C = (L + R) / 2;
 4     if (a[L] > a[C]) swap(&a[L], &a[C]);
 5     if (a[L] > a[R]) swap(&a[L], &a[R]);
 6     if (a[C] > a[R]) swap(&a[C], &a[R]);
 7     //swap(&a[R], &a[R - 1]);
 8     swap(&a[R-1], &a[C]);
 9     return a[R-1];
10 }
11 
12 void Qsort(elemtype a[], int L, int R)
13 {
14     int pivot,i,j;
15     if (L + 3 <= R)
16     {       
17         i = L; 
18         j = R - 1;
19         pivot = median3(a, L, R);
20             while (1)
21             {
22                 while (a[++i] < pivot) {}
23                 while (a[--j] > pivot) {}
24                 if (i < j)
25                 {
26                     swap(&a[i], &a[j]);
27                 }
28                 else
29                     break;
30             }
31         swap(&a[i], &a[R - 1]);    
32         Qsort(a, L, i-1);
33         Qsort(a, i + 1, R);
34     }
35     else
36     Insert_sort(a + L, R - L + 1);
37 }
38 
39 void Quick_sort(elemtype a[])
40 {
41     Qsort(a, 0, N - 1);
42 }

堆排序:perdown()将树调整为大顶堆,每次a[0]与a[i]交换,再调整0-i的树为大顶堆。

时间复杂度:
O(NlogN)

 1 void percdown(elemtype a[], int r, int N)//此函数作用:在根节点,左子和右子之间,选出最大的一个作为新的根节点,循环的作用:使得交换数据后的子节点为根的树同样满足根节点最大的条件(可以用递归实现)。
 2 {
 3     int child;
 4     int temp;
 5     //for (i = N / 2; 2*i + 1 < N; i = child)
 6     temp = a[r]; // temp 不需要动
 7     for (; 2 * r + 1 < N; r = child)
 8     {
 9         child = 2 * r + 1;
10         if (2 * r + 2 < N && a[2 * r + 2] > a[2 * r + 1]) //如果下标不越界而且右子大于左子
11             child++;//child更新为右子的下标
12         if (a[child] > temp&& child < N) //如果子确实大于个根,则交换二者的值,否则不进行任何操作,直接退出。这一步实际上完成了:根,左,右三者比较且选出最大的一个值作为根节点。
13         {
14             a[r] = a[child];
15         }
16         else
17             break;
18     }
19     a[r] = temp; //即a[child] = temp实现了a[r] 与 a[child]进行数据交换。
20 }
21 
22 void Heap_Sort(elemtype a[])
23 {
24     //build heap
25     for (int i = N / 2; i >= 0; i--)//从每一个根节点开始调用percdown(0 - N/2)
26     {
27         percdown(a, i, N);
28     }
29     //delete max
30     for (int i = N - 1; i > 0; i--) //交换数组的第一个数据和最后一个数据,然后进行一次percdown调整为大顶堆,再进行下一次循环。
31     {
32         swap(&a[0], &a[i]);
33         percdown(a, 0, i);
34     }
35 }
  1 #include <iostream>
  2 #include <string>
  3 #include <cmath>
  4 #include <math.h>
  5 
  6 using namespace std;
  7 typedef long int elemtype;
  8 int N;
  9 
 10 void bubble_sort(long int a[])
 11 {
 12     for (int i = 0; i < N-1; i++)
 13     {    
 14         int flag=0;
 15         for (int j = 0; j < N-i-1; j++)
 16         {
 17             if (a[j] > a[j + 1])
 18             {
 19                 flag =1;
 20                 long int temp = a[j];
 21                 a[j] = a[j + 1];
 22                 a[j + 1] = temp;
 23             }
 24         }
 25         if(flag == 0) break;
 26     }
 27 }
 28 
 29 
 30 void Insert_sort(elemtype a[], int n )
 31 {
 32     for (int i = 1; i < n; i++)
 33     {
 34         int j;
 35         elemtype tmp = a[i];
 36         for (j = i; j > 0 && tmp < a[j - 1]; j--)
 37         {
 38             a[j] = a[j - 1];
 39         }
 40         a[j] = tmp;
 41     }
 42 }
 43 
 44 void selection_sort(elemtype a[], int n)
 45 {
 46     for(int i=0;i<n-1;i++)
 47     {
 48         int min = i;
 49         for(int j=i;j<n;j++)
 50         {
 51             if(a[j] < a[min])
 52             min = j;
 53         }
 54         if(min != i)
 55         {
 56             int tmp = a[i];
 57             a[i] = a[min];
 58             a[min] = tmp;
 59         }
 60     }
 61 }
 62 
 63 void Shell_sort(elemtype a[])
 64 {
 65     int k;
 66     int Increment=N/2;
 67     for (Increment = N / 2; Increment >= 1; Increment /= 2)
 68     {
 69         for (int j = Increment; j < N; j++)
 70         {
 71             int tmp = a[j];
 72             for (k = j; k - Increment >= 0; k -= Increment)
 73             {
 74                 if (tmp < a[k - Increment])
 75                 {
 76                     a[k] = a[k - Increment];
 77                 }
 78                 else break;
 79             }
 80             a[k] = tmp;
 81         }
 82     }
 83 }
 84 
 85 void swap(elemtype* a, elemtype* b)
 86 {
 87     int temp = *a;
 88     *a = *b;
 89     *b = temp;
 90 }
 91 
 92 void percdown(elemtype a[], int r, int N)//此函数作用:在根节点,左子和右子之间,选出最大的一个作为新的根节点,循环的作用:使得交换数据后的子节点为根的树同样满足根节点最大的条件(可以用递归实现)。
 93 {
 94     int child;
 95     int temp;
 96     //for (i = N / 2; 2*i + 1 < N; i = child)
 97     temp = a[r]; // temp 不需要动
 98     for (; 2 * r + 1 < N; r = child)
 99     {
100         child = 2 * r + 1;
101         if (2 * r + 2 < N && a[2 * r + 2] > a[2 * r + 1]) //如果下标不越界而且右子大于左子
102             child++;//child更新为右子的下标
103         if (a[child] > temp&& child < N) //如果子确实大于个根,则交换二者的值,否则不进行任何操作,直接退出。这一步实际上完成了:根,左,右三者比较且选出最大的一个值作为根节点。
104         {
105             a[r] = a[child];
106         }
107         else
108             break;
109     }
110     a[r] = temp; //即a[child] = temp实现了a[r] 与 a[child]进行数据交换。
111 }
112 
113 void Heap_Sort(elemtype a[])
114 {
115     //build heap
116     for (int i = N / 2; i >= 0; i--)//从每一个根节点开始调用percdown(0 - N/2)
117     {
118         percdown(a, i, N);
119     }
120     //delete max
121     for (int i = N - 1; i > 0; i--) //交换数组的第一个数据和最后一个数据,然后进行一次percdown调整为大顶堆,再进行下一次循环。
122     {
123         swap(&a[0], &a[i]);
124         percdown(a, 0, i);
125     }
126 }
127 
128 void merge(elemtype a[], elemtype tmp[], int L, int R, int RE)
129 {
130     int LE = R - 1;
131     int num = RE - L + 1;
132     int L2 = L;
133     while (L <= LE && R <= RE)
134     {
135         if (a[L] <= a[R])
136         {
137             tmp[L2++] = a[L++];
138         }
139         else if (a[R] < a[L])
140         {
141             tmp[L2++] = a[R++];
142         }
143     }
144     while (L <= LE)
145     {
146         tmp[L2++] = a[L++];
147     }
148     while (R <= RE)
149     {
150         tmp[L2++] = a[R++];
151     }
152     for (int i = 0; i < num; i++, RE--)
153     {
154         a[RE] = tmp[RE];
155     }
156 }
157 
158 void Msort(elemtype a[], elemtype tmp[], int L, int R)
159 {
160     int C;
161     if (L < R)
162     {
163         C = (L + R) / 2;
164         Msort(a, tmp, L, C);
165         Msort(a, tmp, C + 1, R);
166         merge(a, tmp, L, C + 1, R);
167     }
168 }
169 
170 void Merge_sort(elemtype a[])
171 {
172     elemtype* tmp = new elemtype[N * sizeof(elemtype)];
173     if (NULL == tmp)
174     {
175         cerr << "error" << endl;
176         return;
177     }
178     else
179     {
180         Msort(a, tmp, 0, N - 1);
181         delete[]tmp;
182     }
183 }
184 
185 elemtype median3(elemtype a[], int L, int R)
186 {
187     int C = (L + R) / 2;
188     if (a[L] > a[C]) swap(&a[L], &a[C]);
189     if (a[L] > a[R]) swap(&a[L], &a[R]);
190     if (a[C] > a[R]) swap(&a[C], &a[R]);
191     //swap(&a[R], &a[R - 1]);
192     swap(&a[R-1], &a[C]);
193     return a[R-1];
194 }
195 
196 void Qsort(elemtype a[], int L, int R)
197 {
198     int pivot,i,j;
199     if (L + 3 <= R)
200     {       
201         i = L; 
202         j = R - 1;
203         pivot = median3(a, L, R);
204             while (1)
205             {
206                 while (a[++i] < pivot) {}
207                 while (a[--j] > pivot) {}
208                 if (i < j)
209                 {
210                     swap(&a[i], &a[j]);
211                 }
212                 else
213                     break;
214             }
215         swap(&a[i], &a[R - 1]);    
216         Qsort(a, L, i-1);
217         Qsort(a, i + 1, R);
218     }
219     else
220     Insert_sort(a + L, R - L + 1);
221 }
222 
223 void Quick_sort(elemtype a[])
224 {
225     Qsort(a, 0, N - 1);
226 }
227 
228 int main()
229 {
230     cin >> N;
231     long int* a = new long int[N];
232     for (int i = 0; i < N; i++)
233     {
234         int temp;
235         cin >> temp;
236         a[i] = temp;
237     }
238     //bubble_sort(a);
239     //selection_sort(a, N);
240     //Insert_sort(a, N);
241     //Shell_sort(a);
242     Heap_Sort(a);
243     //Merge_sort(a);
244     //Quick_sort(a);
245 
246     for (int i = 0; i < N; i++)
247     {
248         if (i == N - 1)
249             cout << a[i];
250         else
251             cout << a[i] << " ";
252     }
253 
254     return 0;
255 }
View Code

结果对比:

冒泡:

选择:

插入:

希尔:

堆排:

归并:

快排:

猜你喜欢

转载自www.cnblogs.com/2020R/p/12730689.html