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}