数组排序 —— 常用基础数组排序算法(冒泡、选择、插入、归并、快速、堆、希尔、计数、基数排序)
2016-08-13 10:04
441 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LiveRock_lalala/article/details/52197830
冒泡排序
解题思路
- 1 ~N个数字,”自己”与”下一位”比较,选中最大的放在”下一位”,再以”下一位”为”自己”与”下一位”比较,直到选出最大的数字放在最后
- 1~ N-1 个数字,重复第一步骤操作
- 直到剩下最后一个数字
代码思路
代码
public int[] bubbleSort(int[] A, int n) { int temp = 0; // “需要排序”的个数 for (int i = 0; i < n-1; i++){ // 选出最大的一位放在“需要排序”的最后 for (int j = 0; j < n-1-i; j++){ if (A[j] > A[j+1]){ temp = A[j]; A[j] = A[j+1]; A[j+1] = temp; } } } return A; }
选择排序
解题思路
- 从1 ~ N 个数字中选择最小的数字放在”第一个”
- 从2 ~ N 个….(重复第一步骤)
- 直到剩下最后一个数字
代码思路
代码
public int[] selectionSort(int[] A, int n) { int temp = 0; for (int i = 0; i < n-1; i++){ for (int j = i; j < n; j++){ if (A[i] > A[j]){ temp = A[i]; A[i] = A[j]; A[j] = temp; } } } return A; }
插入排序
解题思路
- 第2个数与第1个数比较,小的插入前边
- 第3个数与依次和前2个比较,插入比它小的位置
- 依次重复步骤2
- 直到剩下0个数
代码思路
代码
public int[] insertionSort(int[] A, int n) { int temp = 0; for (int i = 1; i < n; i++){ int current = i; for (int j = i-1; j >= 0; j--){ if (A[current] < A[j]){ temp = A[current]; A[current] = A[j]; A[j] = temp; current = j; } } } return A; }
归并排序
解题思路
分类:
- 按照递归方法,两两平分,直到长度为“1”;
合并:
- 相邻的两两数字 长度为“1”的合并区间,且排好序;
相邻的两两数字 长度为“2”的合并区间,且排好序;- 相邻的两两数字 长度为“3”的合并区间,且排好序;
- 直到长度为“N”
提示:
两个有序数据的合并 排序算法。
代码思路
代码
public int[] mergeSort(int[] A, int n) { sort(A, 0, n-1); return A; } public void sort(int[] A, int left, int right){ if (left >= right) return ; int middle = (left + right) / 2; // 分类 sort(A, left, middle); sort(A, middle+1 , right); // 合并且从小排序 merge(A, left, middle, right); } public void merge(int[] A, int left, int middle, int right){ // 缓存数组; int[] buffer = new int[right-left+1]; // 缓存索引; int bufferIndex = 0; // 左边索引 int leftIndex = left; // 右边索引 int rightIndex = middle+1; // 将最小的数字存进缓存数组( 两个有序数据的合并 排序算法) while (leftIndex <= middle && rightIndex <= right){ if (A[leftIndex] < A[rightIndex]){ buffer[bufferIndex++] = A[leftIndex++]; } else{ buffer[bufferIndex++] = A[rightIndex++]; } } // 将左边还剩余的数字存入数组 while (leftIndex <= middle){ buffer[bufferIndex++] = A[leftIndex++]; } // 将右边还剩余的数字存入数组 while (rightIndex <= right){ buffer[bufferIndex++] = A[rightIndex++]; } // 将缓存数组数据存进"A"源数组里 bufferIndex = 0; for (int i = left; i <= right; i++){ A[i] = buffer[bufferIndex++]; } }
快速排序
解题思路
- 选中第一个数据(可随机数据),进行排序,小于该数据,放左边,大于放右右,且返回该数据最终所在的索引
- 如此进行遍历…
提示:
划分过程时间复杂度为O(N)
代码思路
代码
public int[] quickSort(int[] A, int n) { if (n > 0){ quick(A, 0, n-1); } return A; } public void quick(int[] A, int low, int high){ if (low < high){ // 排序划分 int middle = getMiddle(A, low, high); quick(A, low, middle); quick(A, middle+1, high); } } public int getMiddle(int[] A, int low, int high){ int temp = A[low]; // 小于 temp 放左边,大于 temp 放右边 while (low < high) { while (low < high && A[high] >= temp){ high--; } A[low] = A[high]; while (low < high && A[low] <= temp){ low++; } A[high] = A[low]; } A[low] = temp; return low; }
堆排序
解题思路
大根堆,小根子
以下所建的堆是大根堆
构建堆,且每个节点为子节点的最大值(需要对每个节点进行排序)
a)先比较子节点,选出一个最大值
b)最大子节点与节点比较。
c)如果节点小于子节点,交换,节点继续与字字节点比较,重复步骤a、b
d)最终达到节点(包括交换后的子节点)为最大值的目的把第一个值与最后一直交换,个数为n-1,继续重复步骤1(只需要对第一个节点排序)
- 直到只剩下最后一个数
代码思路
代码
public static void buildHeap(int[] A, int node, int n) { int temp = A[node]; // 因为从 0 开始,所以需要加上 1 for (int i = node * 2 + 1; i < n; i = i*2 +1) { // 防止没有右节点 if (i < n-1){ // 左右节点比较 if (A[i] < A[i + 1]){ i++; } } // node节点与子节点比较,如果大于就不需要再比较了 if (temp >= A[i]) { break; } A[node] = A[i]; node = i; } A[node] = temp; } public static void swap(int[] A, int a, int b) { int temp = A[a]; A[a] = A[b]; A[b] = temp; } public static int[] heapSort(int[] A, int n) { // 开始的时候先排序,让每个节点为子节点的最大数 for (int i = n / 2-1; i >= 0; i--) { buildHeap(A, i, n); } // 将第一位根节点最大数与最后一位交换,个数减一,接着构建根节点,再交换... for (int i = n-1; i > 0; i--) { swap(A, 0, i); // i 为末尾数 buildHeap(A, 0, i); // i 为还剩下的个数,包括 0 位,所以就不减一了! } return A; }
希尔排序
解题思路
- 根据 n/2 分组,直到组的长度为1(插入排序的分组为1,并且进行第二步)
- 一共有feet组,每组都进行头尾排序,且排序后的数据还得继续和前边距离feet长度进行收尾排序(n–, 重复步骤1、2)
提示:
插入排序的步长为1,从开始就和距离为1的比较。希尔排序是插入排序的优化版
代码思路
代码
public int[] shellSort(int[] A, int n) { // 根据 n/2 分组,直到组的长度为1 for (int feet = n/2; feet >= 1; feet = feet/2){ // 一共有feet组,每组都进行头尾排序 for (int i = 0; i < feet; i++){ for (int j = i+feet; j < n; j = j+feet){ int temp = A[j]; int k = 0; // 每组的头尾进行排序,且排序后的数据还得继续和前边距离feet长度进行收尾排序 for (k = j-feet; k >= 0 && A[k] > temp; k = k-feet){ A[k+feet] = A[k]; } A[k+feet] = temp; } } } }
计数排序
解题思路
- 从数组A里获得最大与最小的值
- 根据最大最小值new 一个大小为 max-min 的数组B
- 将无序数组的元素根据 (值 - min) 放入数组B中
- 将数组B里元素有序地放入源无序数组中
代码思路
代码
public int[] countingSort(int[] A, int n) { int min = A[0]; int max = A[0]; // 从数组里获得最大与最小的值 for (int i = 1; i < n; i++){ min = Math.min(min, A[i]); max = Math.max(max, A[i]); } // 根据最大最小值new 一个大小为 max-min 的数组B int[] B = new int[max-min+1]; // 将无序数组的元素根据 (值 - min) 放入数组B中 for (int i = 0; i < n; i++){ B[A[i]-min] += 1; } // 将数组B里元素有序地放入源无序数组中 int index = 0; for (int i = 0; i < B.length; i++){ while(B[i] > 0){ A[index++] = i+min; B[i]--; } } return A; }
基数排序
解题思路
- 求出数组里最大数据,且根据最大数求出最大的位数
- 首先进行 d = 1 (个数) 分别装桶,然后按顺序倒出来
- 再进行 d = 2 (十数)分别装桶,然后按顺序倒出来
- 直到d = 最大的位数
代码思路
代码
public int[] radixSort(int[] A, int n) { // 构建二维水桶 int bucket[][] = new int[10][A.length]; // 每个位数(0~9)装的数字个数 int count[] = new int[10]; /** * 取最大值,且求出最大的位数 **/ int max = A[0]; for (int i = 1; i < A.length; i++){ max = Math.max(max, A[i]); } int d = 1; // 位数 int a = 10; // 10的倍数,求商 while ((max / a) > 0){ a *= 10; d++; } a = 1; int num = 0; while (d > 0){ // 位数排序,例如 d = 1时,为个数排序, d = 2时,为十数排序... for (int i = 0; i < A.length; i++){ num = A[i] / a % 10; bucket[num][count[num]++] = A[i]; } // 将排序好的数据重新装到源A数组里 int index = 0; for (int i = 0; i < 10; i++){ for (int j = 0; j < count[i]; j++){ A[index++] = bucket[i][j]; } count[i] = 0; } a *= 10; d--; } return A; }
相关文章推荐
- 排序算法大集合,插入、选择、冒泡、希尔、堆、归并、快速排序,总有一款适合你
- 常见内部排序算法 简单数组实现与分析(快速(偶原创partition函数,望众高手指正)、归并、希尔、插入、选择、冒泡)
- 数组排序(插入、选择、希尔、堆、归并、快速、冒泡)
- 常用排序算法总结(插入、冒泡、选择、希尔、快速、归并、堆)
- 排序算法Java描述:选择、冒泡、插入、希尔、归并、快速及三向切分快速排序
- PHP四种基础排序算法--冒泡,直接插入,快速和选择排序
- 十种排序算法总结(冒泡、插入、选择、希尔、归并、堆、快速,计数,桶,基数)[转]
- Java 基础排序算法(冒泡,比较,插入,选择,希尔,堆,归并)
- 数据结构各种排序法及核心思想(冒泡、鸡尾酒、选择、插入、二分法、希尔、堆、归并、快速)
- 十种排序算法总结(冒泡、插入、选择、希尔、归并、堆、快速,计数,桶,基数)
- 各种排序算法(冒泡、选择、快排、插入、希尔、堆排、归并、计数、基数)
- 从零开始_学_数据结构(六)——排序(冒泡、插入、希尔、简单选择、归并、快速)
- 《冒泡,选择,插入,归并,希尔,快速》排序算法java实现一览
- 十种排序算法总结(冒泡、插入、选择、希尔、归并、堆、快速,计数,桶,基数)
- C语言常用排序——直接插入,冒泡,选择,希尔,快速,堆排序
- 列表排序(冒泡、选择、插入、快速、堆、归并、希尔)
- Java实现各大经典排序算法(插入、希尔、简单选择、冒泡、快速、归并)
- [置顶] 十种排序算法总结(冒泡、插入、选择、希尔、归并、堆、快速,计数,桶,基数)
- 七种排序算法总结(冒泡、插入、选择、希尔、归并、堆、快速)
- c# 自定义排序类(冒泡、选择、插入、希尔、快速、归并、堆排序等)