您的位置:首页 > 其它

数组排序 —— 常用基础数组排序算法(冒泡、选择、插入、归并、快速、堆、希尔、计数、基数排序)

2016-08-13 10:04 441 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LiveRock_lalala/article/details/52197830

冒泡排序

解题思路

  1. 1 ~N个数字,”自己”与”下一位”比较,选中最大的放在”下一位”,再以”下一位”为”自己”与”下一位”比较,直到选出最大的数字放在最后
  2. 1~ N-1 个数字,重复第一步骤操作
  3. 直到剩下最后一个数字

代码思路

代码

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. 从1 ~ N 个数字中选择最小的数字放在”第一个”
  2. 从2 ~ N 个….(重复第一步骤)
  3. 直到剩下最后一个数字

代码思路

代码

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;
}

插入排序

解题思路

  1. 第2个数与第1个数比较,小的插入前边
  2. 第3个数与依次和前2个比较,插入比它小的位置
  3. 依次重复步骤2
  4. 直到剩下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”;

合并:

  1. 相邻的两两数字 长度为“1”的合并区间,且排好序;
    相邻的两两数字 长度为“2”的合并区间,且排好序;
  2. 相邻的两两数字 长度为“3”的合并区间,且排好序;
  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++];
}
}

快速排序

解题思路

  1. 选中第一个数据(可随机数据),进行排序,小于该数据,放左边,大于放右右,且返回该数据最终所在的索引
  2. 如此进行遍历…

提示:

划分过程时间复杂度为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;
}

堆排序

解题思路

大根堆,小根子
以下所建的堆是大根堆

  1. 构建堆,且每个节点为子节点的最大值(需要对每个节点进行排序)

    a)先比较子节点,选出一个最大值
    b)最大子节点与节点比较。
    c)如果节点小于子节点,交换,节点继续与字字节点比较,重复步骤a、b
    d)最终达到节点(包括交换后的子节点)为最大值的目的

  2. 把第一个值与最后一直交换,个数为n-1,继续重复步骤1(只需要对第一个节点排序)

  3. 直到只剩下最后一个数

代码思路

代码

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;
}

希尔排序

解题思路

  1. 根据 n/2 分组,直到组的长度为1(插入排序的分组为1,并且进行第二步)
  2. 一共有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;
}
}
}
}

计数排序

解题思路

  1. 从数组A里获得最大与最小的值
  2. 根据最大最小值new 一个大小为 max-min 的数组B
  3. 将无序数组的元素根据 (值 - min) 放入数组B中
  4. 将数组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;
}

基数排序

解题思路

  1. 求出数组里最大数据,且根据最大数求出最大的位数
  2. 首先进行 d = 1 (个数) 分别装桶,然后按顺序倒出来
  3. 再进行 d = 2 (十数)分别装桶,然后按顺序倒出来
  4. 直到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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐