赞
踩
标签(空格分隔): 数据结构和算法
概念
在排序问题中,通常将数据元素称为记录。
排序的依据是关键字之间的大小关系,那么对同一记录集合,针对不同的关键字进行排序,可以得到不同的序列。
分类
插入排序类
选择排序类
交换排序类
归并排序类
冒泡排序的要点
代码实现
#include <stdio.h> void BubbleSort(int k[], int n) { int i, j, temp, count1=0, count2=0; for( i=0; i < n-1; i++ ) { for( j=i+1; j < n; j++ ) { count1++; if( k[i] > k[j] ) { count2++; temp = k[j]; k[j] = k[i]; k[i] = temp; } } } printf("总共进行了%d次比较,进行了%d次移动!\n", count1, count2); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; BubbleSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
#include <stdio.h> void BubbleSort(int k[], int n) { int i, j, temp, count1=0, count2=0; int flag = 1; for( i=0; i < n-1 && flag; i++ ) { for( j=n-1; j > i; j-- ) { count1++; flag = 0; if( k[j-1] > k[j] ) { count2++; temp = k[j-1]; k[j-1] = k[j]; k[j] = temp; flag = 1; } } } printf("总共进行了%d次比较,进行了%d次移动!\n", count1, count2); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; BubbleSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
选择排序算法就是通过n-i次关键字间的比较,从n-i+1个记录中最小的记录,并和第i(1<=i<=n)个记录交换。
代码实现
#include <stdio.h> void SelectSort(int k[], int n) { int i, j, min, temp, count1=0, count2=0; for( i=0; i < n-1; i++ ) { min = i; for( j=i+1; j < n; j++ ) { count1++; if( k[j] < k[min] ) { min = j; } } if( min != i ) { count2++; temp = k[min]; k[min] = k[i]; k[i] = temp; } } printf("总共进行了%d次比较,进行了%d次移动!\n", count1, count2); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; SelectSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
直接插入排序算法(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增加1的有序表。
代码实现
#include <stdio.h> void InsertSort(int k[], int n) { int i, j, temp; for( i=1; i < n; i++ ) { if( k[i] < k[i-1] ) { temp = k[i]; for( j=i-1; k[j] > temp; j-- ) { k[j+1] = k[j]; } k[j+1] = temp; } } } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; InsertSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
初始关键字 | 49 | 38 | 65 | 97 | 76 | 13 | 27 | 49 | 55 | 04 |
---|---|---|---|---|---|---|---|---|---|---|
一趟排序结果 | 13 | 27 | 49 | 55 | 04 | 49 | 38 | 65 | 97 | 76 |
二趟排序结果 | 13 | 04 | 49 | 38 | 27 | 49 | 55 | 65 | 97 | 76 |
三趟排序结果 | 04 | 13 | 27 | 38 | 49 | 49 | 55 | 65 | 76 | 97 |
#include <stdio.h> void ShellSort(int k[], int n) { int i, j, temp; int gap = n; do { gap /= 3; for( i=gap; i < n; i++ ) { if( k[i] < k[i-gap] ) { temp = k[i]; for( j=i-gap; k[j] > temp; j-=gap ) { k[j+gap] = k[j]; } k[j+gap] = temp; } } } while(gap > 0); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; ShellSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
堆,是具有以下性质的完全二叉树
要点
根结点一定是堆中所有结点最大或者最小者,如果按照层序遍历的方式给结点从1开始编号,则结点之间满足如下关系:
下标i与2i和2i+1是双亲和子女关系
那么把大顶堆和小顶堆用层序遍历存入数组,则一定满足上面的表达式。
堆排序(Heap Sort)就是利用堆进行排序的算法,它的基本思想是:
代码实现
#include <stdio.h> int count = 0; void swap(int k[], int i, int j) { int temp; temp = k[i]; k[i] = k[j]; k[j] = temp; } void HeapAdjust(int k[], int s, int n) { int i, temp; temp = k[s]; // i=2*s:左孩子; 2*s+1: 右孩子 for( i=2*s; i <= n; i*=2 ) { count++; if( i < n && k[i] < k[i+1] ) // 左孩子小于右孩子 { i++; // 使得i指向最大的孩子的下标 } if( temp >= k[i] ) // temp临时存放当前需要调整的双亲。如果大于孩子,则退出循环 { break; } k[s] = k[i]; s = i; } k[s] = temp; } void HeapSort(int k[], int n) { int i; // 从下至上,从右至左,层序遍历 for( i=n/2; i > 0; i-- ) { HeapAdjust(k, i, n); // 构建大顶堆的函数。 k:数组 i:当前双亲结点; n:长度 } for( i=n; i > 1; i-- ) { swap(k, 1, i); // 调整,将第一个元素和最后一个元素进行互换,i是变化的 HeapAdjust(k, 1, i-1); // 重新调整 } } int main() { int i; int a[10] = {-1, 5, 2, 6, 0, 3, 9, 1, 7, 4}; HeapSort(a, 9); printf("总共执行 %d 次比较! \n", count); printf("排序后的结果是: "); for( i=1; i < 10; i++ ) { printf("%d ", a[i]); } printf("\n"); return 0; }
归并排序(Merge Sort)就是利用归并的思想实现的排序方法。它的原理是假设初始有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;然后再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
归并排序的递归实现
// 递归实现 #include <stdio.h> #define MAXSIZE 10 //实现归并,并把最后的结果存放到list1数组 void merging(int *list1, int list1_size, int *list2, int list2_size) { int i, j, k, m; int temp[MAXSIZE]; i = j = k = 0 while( i < list1_size && j < list2_size ) { if( list1[i] < list2[j] ) { temp[k++] = list1[i++]; } else { temp[k++] = list2[j++]; } } while( i < list1_size ) { temp[k++] = list1[i++]; } while( j < list2_size ) { temp[k++] = list2[j++]; } for( m=0; m < (list1_size + list2_size); m++ ) { list1[m] = temp[m]; } } void MergeSort(int k[], int n) { if( n > 1 ) { int *list1 = k; int list1_size = n/2; int *list2 = k + n/2; // 左半部分的地址加上左半部分的尺寸 int list2_size = n - list1_size; MergeSort(list1, list1_size); MergeSort(list2, list2_size); merging(list1, list1_size, list2, list2_size); } } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; MergeSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
// 迭代实现 #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 void MergeSort(int k[], int n) { int i, next, left_min, left_max, right_min, right_max; // 申请空间存放数组 int *temp = (int *)malloc(n * sizeof(int)); // 逐级递增比较 for( i=1; i < n; i*=2 ) // 步长i { for( left_min=0; left_min < n-i; left_min = right_max ) { right_min = left_max = left_min + i; right_max = left_max + i; // 右边的下标最大值只能为n,防止越界 if( right_max > n ) { right_max = n; } // temp数组的下标,由于每次数据都有返回到k,因此每次都需重新置零 next = 0; // 如果左边的数据还没有到分割线且右边的数据也没有到分割线,则循环 while( left_min < left_max && right_min < right_max ) { if( k[left_min] < k[right_min] ) { temp[next++] = k[left_min++]; // 存放较小者 } else { temp[next++] = k[right_min++]; } } // 如果左边的游标没有到达分割线,则需要把数组接回去 // 如果右边的游标没有到达分割线,则说明右边的数据比较大,不需要移动位置 while( left_min < left_max ) { k[--right_min] = k[--left_max]; } while( next > 0 ) { // 将排好序的数组返回给k k[--right_min] = temp[--next]; } } } } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; MergeSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
#include <stdio.h> void swap(int k[], int low, int high) { int temp; temp = k[low]; k[low] = k[high]; k[high] = temp; } int Partition(int k[], int low, int high) { int point; point = k[low]; while( low < high ) { while( low < high && k[high] >= point ) { high--; } swap(k, low, high); while( low < high && k[low] <= point ) { low++; } swap(k, low, high); } return low; } void QSort(int k[], int low, int high) { int point; if( low < high ) { point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边 QSort(k, low, point-1); QSort(k, point+1, high); } } void QuickSort(int k[], int n) { QSort(k, 0, n-1); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; QuickSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
#include <stdio.h> void swap(int k[], int low, int high) { int temp; temp = k[low]; k[low] = k[high]; k[high] = temp; } int Partition(int k[], int low, int high) { int point; int m = low + (high-low)/2; if( k[low] > k[high] ) { swap(k, low, high); } if( k[m] > k[high] ) { swap(k, m, high); } if( k[m] > k[low] ) { swap(k, m, low); } // 将low变成中间值 point = k[low]; while( low < high ) { while( low < high && k[high] >= point ) { high--; } swap(k, low, high); while( low < high && k[low] <= point ) { low++; } swap(k, low, high); } } void QSort(int k[], int low, int high) { int point; if( low < high ) { point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边 QSort(k, low, point-1); QSort(k, point+1, high); } } void QuickSort(int k[], int n) { QSort(k, 0, n-1); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; QuickSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
#include <stdio.h> void swap(int k[], int low, int high) { int temp; temp = k[low]; k[low] = k[high]; k[high] = temp; } int Partition(int k[], int low, int high) { int point; int m = low + (high-low)/2; if( k[low] > k[high] ) { swap(k, low, high); } if( k[m] > k[high] ) { swap(k, m, high); } if( k[m] > k[low] ) { swap(k, m, low); } // 将low变成中间值 point = k[low]; while( low < high ) { while( low < high && k[high] >= point ) { high--; } k[low] = k[high]; while( low < high && k[low] <= point ) { low++; } k[high] = k[low]; } k[low] = point; } void QSort(int k[], int low, int high) { int point; if( low < high ) { point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边 QSort(k, low, point-1); QSort(k, point+1, high); } } void QuickSort(int k[], int n) { QSort(k, 0, n-1); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; QuickSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
#include <stdio.h> #define MAX_LENGTH_INSERT_SORT 7 void ISort(int k[], int n) { int i, j, temp; for( i=1; i < n; i++ ) { if( k[i] < k[i-1] ) { temp = k[i]; for( j=i-1; k[j] > temp; j-- ) { k[j+1] = k[j]; } k[j+1] = temp; } } } void InsertSort(int k[], int low, int high) { ISort(k+low, high-low+1); } void swap(int k[], int low, int high) { int temp; temp = k[low]; k[low] = k[high]; k[high] = temp; } int Partition(int k[], int low, int high) { int point; int m = low + (high-low)/2; if( k[low] > k[high] ) { swap(k, low, high); } if( k[m] > k[high] ) { swap(k, m, high); } if( k[m] > k[low] ) { swap(k, m, low); } // 将low变成中间值 point = k[low]; while( low < high ) { while( low < high && k[high] >= point ) { high--; } k[low] = k[high]; while( low < high && k[low] <= point ) { low++; } k[high] = k[low]; } k[low] = point; } void QSort(int k[], int low, int high) { int point; if( high - low > MAX_LENGTH_INSERT_SORT ) { point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边 QSort(k, low, point-1); QSort(k, point+1, high); } else { InsertSort(k, low, high); } } void QuickSort(int k[], int n) { QSort(k, 0, n-1); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; QuickSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
#include <stdio.h> #define MAX_LENGTH_INSERT_SORT 7 void ISort(int k[], int n) { int i, j, temp; for( i=1; i < n; i++ ) { if( k[i] < k[i-1] ) { temp = k[i]; for( j=i-1; k[j] > temp; j-- ) { k[j+1] = k[j]; } k[j+1] = temp; } } } void InsertSort(int k[], int low, int high) { ISort(k+low, high-low+1); } void swap(int k[], int low, int high) { int temp; temp = k[low]; k[low] = k[high]; k[high] = temp; } int Partition(int k[], int low, int high) { int point; int m = low + (high-low)/2; if( k[low] > k[high] ) { swap(k, low, high); } if( k[m] > k[high] ) { swap(k, m, high); } if( k[m] > k[low] ) { swap(k, m, low); } // 将low变成中间值 point = k[low]; while( low < high ) { while( low < high && k[high] >= point ) { high--; } k[low] = k[high]; while( low < high && k[low] <= point ) { low++; } k[high] = k[low]; } k[low] = point; } void QSort(int k[], int low, int high) { int point; if( high - low > MAX_LENGTH_INSERT_SORT ) { while( low < high ) { point = Partition(k, low, high); // 计算基准点,将小于基准点的数放在左边,大的放在右边 if( point-low < high-point ) { QSort(k, low, point-1); low = point + 1; } else { QSort(k, point+1, high); high = point-1; } } } else { InsertSort(k, low, high); } } void QuickSort(int k[], int n) { QSort(k, 0, n-1); } int main() { int i; int a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8}; QuickSort(a, 10); printf("排序后的结果是: \n"); for( i=0; i < 10; i++ ) { printf("%d", a[i]); } printf("\n"); return 0; }
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 稳定 |
直接插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
希尔排序 | O(nlogn)~O(n^2) | O(n^1.3) | O(n^2) | O(1) | 不稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(nlogn)~O(n) | 不稳定 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。