排序总结
来源:互联网 发布:homer软件 编辑:程序博客网 时间:2024/05/22 09:02
- 冒泡排序
for(int j = 0; j < n - 1; j++) // 每次最大元素就像气泡一样"浮"到数组的最后 { for (int i = 0; i < n - 1 - j; i++) // 依次比较相邻的两个元素,使较大的那个向后移 { if (A[i] > A[i + 1]) // 如果条件改成A[i] >= A[i + 1],则变为不稳定的排序算法 { exchange(A, i, i + 1); } } }
- 选择排序
for (i = 0; i <= n - 2; i++) // 已排序序列的末尾 { min = i; for (j = i + 1; j <= n - 1; j++) // 未排序序列 { if (A[j] < A[min]) // 依次找出未排序序列中的最小值,存放到已排序序列的末尾 { min = j; } } if (min != i) { exchange(A, min, i); // 该操作很有可能把稳定性打乱,所以选择排序是不稳定的排序算法 } }
- 鸡尾酒排序
int left = 0; // 初始化边界 int right = n - 1; while (left < right) { for (int i = left; i < right; i++) // 前半轮,将最大元素放到后面 if (A[i] > A[i + 1]) { exchange(A, i, i + 1); } right--; for (int i = right; i > left; i--) // 后半轮,将最小元素放到前面 if (A[i - 1] > A[i]) { exchange(A, i - 1, i); } left++; }
- 直接插入排序
for (i = 1; i < n; i++) { get = A[i]; // 右手抓到一张扑克牌 j = i - 1; // 拿在左手上的牌总是排序好的 while (j >= 0 && A[j] > get) // 将抓到的牌与手牌从右向左进行比较 { A[j + 1] = A[j]; // 如果该手牌比抓到的牌大,就将其右移 j--; //回到j-1的位置 } A[j+1] = get; // 直到该手牌比抓到的牌小(或二者相等),将抓到的牌插入到该手牌右边(相等元素的相对次序未变,所以插入排序是稳定的) }
- 二分插入排序
for (i = 1; i < n; i++) // 类似抓扑克牌排序 {// 右手抓到一张扑克牌 left = 0; right = i - 1; while (left <= right) // 采用二分法定位新牌的位置 { middle = (left + right) / 2; if (A[middle] > get) right = middle - 1; else left = middle + 1; } for (j = i - 1; j >= left; j--) // 将欲插入新牌位置右边的牌整体向右移动一个单位 { A[j + 1] = A[j]; } A[left] = get; // 将抓到的牌插入手牌 }
- 希尔排序
#include <stdio.h> // 分类 -------------- 内部比较排序// 数据结构 ---------- 数组// 最差时间复杂度 ---- 根据步长序列的不同而不同。已知最好的为O(n(logn)^2)// 最优时间复杂度 ---- O(n)// 平均时间复杂度 ---- 根据步长序列的不同而不同。// 所需辅助空间 ------ O(1)// 稳定性 ------------ 不稳定int main(){ int A[] = { 5, 2, 9, 4, 7, 6, 1, 3, 8 };// 从小到大希尔排序 int n = sizeof(A) / sizeof(int); int i, j, get; int h = 0; while (h <= n) // 生成初始增量 { h = 3*h + 1; } while (h >= 1) { for (i = h; i < n; i++) { j = i - h; get = A[i]; while ((j >= 0) && (A[j] > get)) { A[j + h] = A[j]; j = j - h; } A[j + h] = get; } h = (h - 1) / 3; // 递减增量 } printf("希尔排序结果:"); for (i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0;}
- 归并排序
#include <stdio.h>#include <limits.h> // 包含极限值的头文件,这里用到了无穷大INT_MAX// 分类 -------------- 内部比较排序// 数据结构 ---------- 数组// 最差时间复杂度 ---- O(nlogn)// 最优时间复杂度 ---- O(nlogn)// 平均时间复杂度 ---- O(nlogn)// 所需辅助空间 ------ O(n)// 稳定性 ------------ 稳定int L[10]; // 两个子数组定义成全局变量(辅助存储空间,大小正比于元素的个数)int R[10];void merge(int A[], int left, int middle, int right)// 合并两个已排好序的数组A[left...middle]和A[middle+1...right]{ int n1 = middle - left + 1; // 两个数组的大小 int n2 = right - middle; for (int i = 0; i < n1; i++) // 把两部分分别拷贝到两个数组中 L[i] = A[left + i]; for (int j = 0; j < n2; j++) R[j] = A[middle + j + 1]; L[n1] = INT_MAX; // 使用无穷大作为哨兵值放在子数组的末尾 R[n2] = INT_MAX; // 这样可以免去检查某个子数组是否已读完的步骤 int i = 0; int j = 0; for (int k = left; k <= right; k++) // 依次比较两个子数组中的值,每次取出更小的那一个放入原数组 { if (L[i] <= R[j]) { A[k] = L[i]; i++; } else { A[k] = R[j]; j++; } }}void mergesort_recursion(int A[], int left, int right) // 递归实现的归并排序(自顶向下){ int middle = (left + right) / 2; if (left < right) // 当待排序的序列长度为1时(left == right),递归“开始回升” { mergesort_recursion(A, left, middle); mergesort_recursion(A, middle + 1, right); merge(A, left, middle, right); }}void mergesort_iteration(int A[], int left, int right) // 非递归(迭代)实现的归并排序(自底向上){ int low, middle, high; // 子数组索引,前一个为A[low...middle],后一个子数组为A[middle+1...high] for (int size = 1; size <= right - left; size *= 2) // 子数组的大小初始为1,每轮翻倍 { low = left; while (low + size - 1 <= right - 1 )// 后一个子数组存在(需要归并) { middle = low + size - 1; high = middle + size; if (high > right) // 后一个子数组大小不足size high = right; merge(A, low, middle, high); low = high + 1; // 前一个子数组索引向后移动 } }}int main(){ int A1[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; // 从小到大归并排序 int A2[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; int n1 = sizeof(A1) / sizeof(int); int n2 = sizeof(A2) / sizeof(int); mergesort_recursion(A1, 0, n1 - 1); // 递归实现 mergesort_iteration(A2, 0, n2 - 1); // 非递归实现 printf("递归实现的归并排序结果:"); for (int i = 0; i < n1; i++) { printf("%d ",A1[i]); } printf("\n"); printf("非递归实现的归并排序结果:"); for (int i = 0; i < n2; i++) { printf("%d ", A2[i]); } printf("\n"); return 0;}
- 堆排序
#include <stdio.h>// 分类 -------------- 内部比较排序// 数据结构 ---------- 数组// 最差时间复杂度 ---- O(nlogn)// 最优时间复杂度 ---- O(nlogn)// 平均时间复杂度 ---- O(nlogn)// 所需辅助空间 ------ O(1)// 稳定性 ------------ 不稳定int heapsize; // 堆大小void exchange(int A[], int i, int j) // 交换A[i]和A[j]{ int temp = A[i]; A[i] = A[j]; A[j] = temp;}void heapify(int A[], int i) // 堆调整函数(这里使用的是最大堆){ int leftchild = 2 * i + 1; // 左孩子索引 int rightchild = 2 * i + 2; // 右孩子索引 int largest; // 选出当前结点与左右孩子之中的最大值 if (leftchild < heapsize && A[leftchild] > A[i]) largest = leftchild; else largest = i; if (rightchild < heapsize && A[rightchild] > A[largest]) largest = rightchild; if (largest != i) { exchange(A, i, largest); // 把当前结点和它的最大(直接)子节点进行交换 heapify(A, largest); // 递归调用,继续从当前结点向下进行堆调整 }}void buildheap(int A[], int n) // 建堆函数{ heapsize = n; for (int i = heapsize / 2 - 1; i >= 0; i--) // 对每一个非叶结点 heapify(A, i); // 不断的堆调整}void heapsort(int A[], int n){ buildheap(A, n); for (int i = n - 1; i >= 1; i--) { exchange(A, 0, i); // 将堆顶元素(当前最大值)与堆的最后一个元素互换(该操作很有可能把后面元素的稳定性打乱,所以堆排序是不稳定的排序算法) heapsize--; // 从堆中去掉最后一个元素 heapify(A, 0); // 从新的堆顶元素开始进行堆调整 }}int main(){ int A[] = { 5, 2, 9, 4, 7, 6, 1, 3, 8 };// 从小到大堆排序 int n = sizeof(A) / sizeof(int); heapsort(A, n); printf("堆排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0;}
- 快速排序
#include <stdio.h>// 分类 ------------ 内部比较排序// 数据结构 --------- 数组// 最差时间复杂度 ---- 每次选取的基准都是最大的元素(或者每次都是最小),导致每次只划分出了一个子序列,需要进行n-1次划分才能结束递归,时间复杂度为O(n^2)// 最优时间复杂度 ---- 每次选取的基准都能使划分均匀,只需要logn次划分就能结束递归,时间复杂度为O(nlogn)// 平均时间复杂度 ---- O(nlogn)// 所需辅助空间 ------ O(logn)~O(n),主要是递归造成的栈空间的使用(用来保存left和right等局部变量),取决于递归树的深度// 一般为O(logn),最差为O(n)(基本有序的情况)// 稳定性 ---------- 不稳定void exchange(int A[], int i, int j) // 交换A[i]和A[j]{ int temp = A[i]; A[i] = A[j]; A[j] = temp;}int partition(int A[], int left, int right) // 划分函数{ int pivot = A[right]; // 选择最后一个元素作为基准 int tail = left - 1; // tail为小于基准的子数组最后一个元素的索引 for (int i = left; i < right; i++) // 遍历基准以外的其他元素 { if (A[i] <= pivot) // 把小于等于基准的元素放到前一个子数组中 { tail++; exchange(A, tail, i); } } exchange(A, tail + 1, right); // 最后把基准放到前一个子数组的后边,剩下的子数组既是大于基准的子数组 // 该操作很有可能把后面元素的稳定性打乱,所以快速排序是不稳定的排序算法 return tail + 1; // 返回基准的索引}void quicksort(int A[], int left, int right){ int pivot_index; // 基准的索引 if (left < right) { pivot_index = partition(A, left, right); quicksort(A, left, pivot_index-1); quicksort(A, pivot_index+1, right); }}int main(){ int A[] = { 5, 2, 9, 4, 7, 6, 1, 3, 8 };// 从小到大快速排序 int n = sizeof(A) / sizeof(int); quicksort(A, 0, n - 1); printf("快速排序结果:"); for (int i = 0; i < n; i++) { printf("%d ",A[i]); } printf("\n"); return 0;}
阅读全文
0 0
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序 -- 总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- 排序总结
- java基础--6.异常
- 百度车联网API
- red5+java打造直播平台系列 初级
- Python FTP文件传输实现
- 开源项目地址-cloudera版本大数据框架
- 排序总结
- 堆排序(heap Sort)
- oracle怎么让表的一个属性有缺省值
- Mybatis整合Spring
- 常用随机变量及其概率分布
- git本地仓库的概念
- iOS 处理中文网址路径转换
- 浏览器怎么加载页面的?
- android 7.0 添加多用户时跳过wifi报错