3.2. 排序技术
基于比较的排序分类
插入排序
交换排序
选择排序
归并排序
3.2.1. 直接插入排序
基本思想: 前面i个记录是有序的, 新的元素,找到位置,插入到对应位置。 这样有序的个数增加1 , 经过多次,所有的元素都是有序的。
核心问题:
如何初始构造有序序列
如何确定插入位置。
如何插入移动。
3.2.2. 希尔排序
基本思想: 将整个待排序记录分割成若干子序列,在子序列分别进行直接插入排序,待整个序列基本有序时候,对全体记录进行插入排序。
核心问题:
如何分割
子序列如何进行直接插入排序
3.2.3. 冒泡排序
3.2.4. 冒泡排序
3.2.5. 排序实现的常见实现
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <assert.h>
5
6// 交换
7void swap(int *arr, i, j) {
8 int temp = arr[i];
9 arr[i] = arr[j];
10 arr[j] = temp;
11 return;
12}
13
14// 打印
15void print_arr_item(int *str, int size) {
16 assert(str != NULL);
17 printf("size=%d\n",size);
18 for (int i = 0; i < size; i++) {
19 printf("%d\t", str[i]);
20 }
21 printf("\n");
22
23}
24
25/// 查找arr有序数组中(0-lastIndex)有序部分item应该插入那个位置。
26int find_pos_quick(int *arr, int start, int end, int item) {
27 // int pos = end +1 ;
28 int left = start;
29 int right = end;
30 int mid;
31 while (left <= right) {
32 mid = (left + right) / 2;
33 if (item > arr[mid]) {
34 left = mid + 1;
35 } else {
36 right = mid - 1;
37 }
38 }
39
40 return left;
41}
42
43/// 查找arr有序数组中(0-lastIndex)有序部分item应该插入那个位置。
44int find_pos(int *arr, int start, int end, int item) {
45 int pos = end + 1;
46 for (int j = end; j >= 0 && arr[j] > item; --j) {
47 pos = j;
48 }
49 return pos;
50}
51
52// 移动元素。
53int move_pos(int *arr, int start, int end) {
54 for (int i = end; i >= start; --i) {
55 arr[i + 1] = arr[i];
56 }
57}
58
59void insert_sort(int *arr, int size) {
60 if (size <= 1) {
61 return;
62 }
63 // 先认定i=0 这个是有序的, 第一个要插入的就从第二个元素(index=1)开始。
64 for (int i = 1; i < size; ++i) {
65 // 记录当前值和索引位置。 因为可能发生移动, 会覆盖了这个值,需要暂存下。
66 // 暂存的这个值要插入那个位置,最终呢, 需要pos这个标示下。
67 int temp = arr[i];
68 int pos = i;
69
70 // (0=>i-1) 都是有序的当前, 当前要做的就是将i插入进去,让0=>i是有序的。
71 // 应该优先给有序的最后一个元素j=i-1比较,然后再给倒数第二个比较。
72 // 如果temp值小于最后一个元素的话, 那就移动一次,插入位置就从移动后腾出来的位置啦。
73// for (int j = i-1; j >=0 && arr[j] > temp ; --j) {
74// arr[j+1] = arr[j] ;
75// pos = j ;
76// }
77 pos = find_pos_quick(arr, 0, i - 1, temp);
78 //printf("%d\t", pos);
79// pos= find_pos(arr,0,i-1,temp);
80// printf("%d\t",pos);
81 //printf("\n");
82 move_pos(arr, pos, i - 1);
83 arr[pos] = temp;
84
85 }
86 return;
87}
88
89void shell_sort(int *arr, int size ){
90 if (size<=1){
91 return ;
92 }
93 for (int d=size/2 ; d>=1;d=d/2){
94 for (int i = d; i <size ; i+=1) {
95 int pos =i ;
96 int temp = arr[i] ;
97
98 for (int j = i-d; j >=0 && arr[j] >temp ; j-=d) {
99 arr[j+d] = arr[j];
100 pos = j;
101 }
102 arr[pos] = temp;
103 }
104 printf("\n%d===start==\n",d);
105 print_arr_item(arr, size);
106 printf("\n%d==end===\n",d);
107 }
108 return ;
109}
110
111void bubble_sort(int *arr, int size ){
112 for (int i = 0; i <size ; ++i) {
113 for (int j = 0; j <size-1 ; ++j) {
114 if (arr[j] > arr[j+1]){
115 swap(arr,j,j+1) ;
116 }
117 }
118 }
119}
120
121void bubble_sort_quick(int *arr, int size ){
122 int exchange = size -1 ;
123 int bound ;
124 // 边界为0 的时候,退出的。
125 while (exchange) {
126 bound = exchange;
127 exchange = 0 ;
128 for (int j = 0; j <bound ; ++j) {
129 if (arr[j] > arr[j+1]){
130 swap(arr,j,j+1) ;
131 // 记录最后一个交换的位置, 说明之后的都是有序的啦。 前面无序。 方便后面缩减边界。
132 exchange = j ;
133 }
134 }
135 }
136}
137
138int partition(int* arr, int start, int end ){
139 int left =start ;
140 int right = end;
141 int value = arr[start];
142
143
144 while (left <right){
145 while(left<right && arr[right] >=value){
146 right -=1 ;
147 }
148 if (left<right){
149 swap(arr,left,right) ;
150 left +=1;
151 }
152
153 while(left<right && arr[left]<value){
154 left +=1;
155 }
156 if (left <right){
157 swap(arr,left,right) ;
158 right-=1;
159 }
160
161 }
162 return left ;
163}
164void quick_sort_v1(int *arr,int start,int end){
165 if (end -start <=0){
166 return;
167 }
168 int pos = partition(arr,start,end);
169 quick_sort_v1(arr,start,pos-1);
170 quick_sort_v1(arr,pos+1,end);
171
172 return;
173}
174
175void quick_sort(int *arr, int size ){
176 if (size <=1){
177 return ;
178 }
179 return quick_sort_v1(arr,0,size-1);
180}
181
182// 选择排序
183select_sort(int *arr ,int size){
184 for (int i = 0; i < size-1; ++i) {
185 int minIndex =i ;
186 int minValue = arr[i] ;
187 for (int j = i+1; j <size ; ++j) {
188 if (arr[j] < minValue){
189 minIndex = j ;
190 minValue = arr[j] ;
191 }
192 }
193 swap(arr,i,minIndex);
194 }
195}
196
197int main() {
198 int str1[12] = {12, 4, 53, 3, 2, 34, 6, 35, 1, 132, 324, 12};
199 int str2[12] = {12, 4, 53, 3, 2, 34, 6, 35, 1, 132, 324, 12};
200 int str3[12] = {12, 4, 53, 3, 2, 34, 6, 35, 1, 132, 324, 12};
201 int str4[12] = {12, 4, 53, 3, 2, 34, 6, 35, 1, 132, 324, 12};
202 int str5[12] = {12, 4, 53, 3, 2, 34, 6, 35, 1, 132, 324, 12};
203 int str6[12] = {12, 4, 53, 3, 2, 34, 6, 35, 1, 132, 324, 12};
204
205 printf("打印排序前的原始结果:\n");
206 print_arr_item(str1, sizeof(str1) / sizeof(*str1));
207 insert_sort(str1, sizeof(str1) / sizeof(*str1));
208 printf("打印排序插入排序的结果:\n");
209 print_arr_item(str1, sizeof(str1) / sizeof(*str1));
210
211
212 printf("打印排序前的原始结果:\n");
213 print_arr_item(str2, sizeof(str2) / sizeof(*str2));
214 shell_sort(str2, sizeof(str2) / sizeof(*str2));
215 printf("打印排序希尔排序的结果:\n");
216 print_arr_item(str2, sizeof(str2) / sizeof(*str2));
217
218 printf("打印排序前的原始结果:\n");
219 print_arr_item(str3, sizeof(str3) / sizeof(*str3));
220 bubble_sort_quick(str3, sizeof(str3) / sizeof(*str3));
221 printf("打印排序冒泡排序的结果:\n");
222 print_arr_item(str3, sizeof(str3) / sizeof(*str3));
223
224 printf("打印排序前的原始结果:\n");
225 print_arr_item(str4, sizeof(str4) / sizeof(*str4));
226 quick_sort(str4, sizeof(str4) / sizeof(*str4));
227 printf("打印排序快速排序的结果:\n");
228 print_arr_item(str4, sizeof(str4) / sizeof(*str4));
229
230 printf("打印排序前的原始结果:\n");
231 print_arr_item(str5, sizeof(str5) / sizeof(*str5));
232 select_sort(str5, sizeof(str5) / sizeof(*str5));
233 printf("打印排序选择排序的结果:\n");
234 print_arr_item(str5, sizeof(str5) / sizeof(*str5));
235}