《漫画算法》源码整理-5 排序算法
Posted GarfieldEr007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《漫画算法》源码整理-5 排序算法相关的知识,希望对你有一定的参考价值。
冒泡排序
import java.util.Arrays;
public class BubbleSort
public static void sort(int array[])
int tmp = 0;
//记录最后一次交换的位置
int lastExchangeIndex = 0;
//无序数列的边界,每次比较只需要比到这里为止
int sortBorder = array.length - 1;
for(int i = 0; i < array.length; i++)
//有序标记,每一轮的初始是true
boolean isSorted = true;
for(int j = 0; j < sortBorder; j++)
if(array[j] > array[j+1])
tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
//有元素交换,所以不是有序,标记变为false
isSorted = false;
//把无序数列的边界更新为最后一次交换元素的位置
lastExchangeIndex = j;
sortBorder = lastExchangeIndex;
if(isSorted)
break;
public static void main(String[] args)
int[] array = new int[]3,4,2,1,5,6,7,8;
sort(array);
System.out.println(Arrays.toString(array));
鸡尾酒排序
import java.util.Arrays;
public class CockTailSort
public static void sort(int array[])
int tmp = 0;
for(int i=0; i<array.length/2; i++)
//有序标记,每一轮的初始是true
boolean isSorted = true;
//奇数轮,从左向右比较和交换
for(int j=i; j<array.length-i-1; j++)
if(array[j] > array[j+1])
tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
//有元素交换,所以不是有序,标记变为false
isSorted = false;
if(isSorted)
break;
//偶数轮之前,重新标记为true
isSorted = true;
//偶数轮,从右向左比较和交换
for(int j=array.length-i-1; j>i; j--)
if(array[j] < array[j-1])
tmp = array[j];
array[j] = array[j-1];
array[j-1] = tmp;
//有元素交换,所以不是有序,标记变为false
isSorted = false;
if(isSorted)
break;
public static void main(String[] args)
int[] array = new int[]2,3,4,5,6,7,8,1;
sort(array);
System.out.println(Arrays.toString(array));
快速排序
import java.util.Arrays;
public class QuickSort
public static void quickSort(int[] arr, int startIndex, int endIndex)
// 递归结束条件:startIndex大等于endIndex的时候
if (startIndex >= endIndex)
return;
// 得到基准元素位置
int pivotIndex = partition(arr, startIndex, endIndex);
// 根据基准元素,分成两部分递归排序
quickSort(arr, startIndex, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, endIndex);
/**
* 分治(双边循环法)
* @param arr 待交换的数组
* @param startIndex 起始下标
* @param endIndex 结束下标
*/
private static int partition(int[] arr, int startIndex, int endIndex)
// 取第一个位置的元素作为基准元素(也可以选择随机位置)
int pivot = arr[startIndex];
int left = startIndex;
int right = endIndex;
while( left != right)
//控制right指针比较并左移
while(left<right && arr[right] > pivot)
right--;
//控制left指针比较并右移
while( left<right && arr[left] <= pivot)
left++;
//交换left和right指向的元素
if(left<right)
int p = arr[left];
arr[left] = arr[right];
arr[right] = p;
//pivot和指针重合点交换
arr[startIndex] = arr[left];
arr[left] = pivot;
return left;
/**
* 分治(单边循环法)
* @param arr 待交换的数组
* @param startIndex 起始下标
* @param endIndex 结束下标
*/
private static int partitionV2(int[] arr, int startIndex, int endIndex)
// 取第一个位置的元素作为基准元素(也可以选择随机位置)
int pivot = arr[startIndex];
int mark = startIndex;
for(int i=startIndex+1; i<=endIndex; i++)
if(arr[i]<pivot)
mark ++;
int p = arr[mark];
arr[mark] = arr[i];
arr[i] = p;
arr[startIndex] = arr[mark];
arr[mark] = pivot;
return mark;
public static void main(String[] args)
int[] arr = new int[] 4,4,6,5,3,2,8,1;
quickSort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr));
使用栈快速排序
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class QuickSortWithStack
public static void quickSort(int[] arr, int startIndex, int endIndex)
// 用一个集合栈来代替递归的函数栈
Stack<Map<String, Integer>> quickSortStack = new Stack<Map<String, Integer>>();
// 整个数列的起止下标,以哈希的形式入栈
Map rootParam = new HashMap();
rootParam.put("startIndex", startIndex);
rootParam.put("endIndex", endIndex);
quickSortStack.push(rootParam);
// 循环结束条件:栈为空时结束
while (!quickSortStack.isEmpty())
// 栈顶元素出栈,得到起止下标
Map<String, Integer> param = quickSortStack.pop();
// 得到基准元素位置
int pivotIndex = partition(arr, param.get("startIndex"), param.get("endIndex"));
// 根据基准元素分成两部分, 把每一部分的起止下标入栈
if(param.get("startIndex") < pivotIndex -1)
Map<String, Integer> leftParam = new HashMap<String, Integer>();
leftParam.put("startIndex", param.get("startIndex"));
leftParam.put("endIndex", pivotIndex -1);
quickSortStack.push(leftParam);
if(pivotIndex + 1 < param.get("endIndex"))
Map<String, Integer> rightParam = new HashMap<String, Integer>();
rightParam.put("startIndex", pivotIndex + 1);
rightParam.put("endIndex", param.get("endIndex"));
quickSortStack.push(rightParam);
/**
* 分治(单边循环法)
* @param arr 待交换的数组
* @param startIndex 起始下标
* @param endIndex 结束下标
*/
private static int partition(int[] arr, int startIndex, int endIndex)
// 取第一个位置的元素作为基准元素(也可以选择随机位置)
int pivot = arr[startIndex];
int mark = startIndex;
for(int i=startIndex+1; i<=endIndex; i++)
if(arr[i]<pivot)
mark ++;
int p = arr[mark];
arr[mark] = arr[i];
arr[i] = p;
arr[startIndex] = arr[mark];
arr[mark] = pivot;
return mark;
public static void main(String[] args)
int[] arr = new int[] 4,7,6,5,3,2,8,1;
quickSort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr));
堆排序
import java.util.Arrays;
public class HeapSort
/**
* 下沉调整
* @param array 待调整的堆
* @param parentIndex 要下沉的父节点
* @param length 堆的有效大小
*/
public static void downAdjust(int[] array, int parentIndex, int length)
// temp保存父节点值,用于最后的赋值
int temp = array[parentIndex];
int childIndex = 2 * parentIndex + 1;
while (childIndex < length)
// 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
if (childIndex + 1 < length && array[childIndex + 1] > array[childIndex])
childIndex++;
// 如果父节点大于等于任何一个孩子的值,直接跳出
if (temp >= array[childIndex])
break;
//无需真正交换,单向赋值即可
array[parentIndex] = array[childIndex];
parentIndex = childIndex;
childIndex = 2 * childIndex + 1;
array[parentIndex] = temp;
/**
* 堆排序(升序)
* @param array 待调整的堆
*/
public static void heapSort(int[] array)
// 1.把无序数组构建成最大堆。
for (int i = (array.length-2)/2; i >= 0; i--)
downAdjust(array, i, array.length);
System.out.println(Arrays.toString(array));
// 2.循环交换集合尾部元素到堆顶,并调节堆产生新的堆顶。
for (int i = array.length - 1; i > 0; i--)
// 最后一个元素和第一元素进行交换
int temp = array[i];
array[i] = array[0];
array[0] = temp;
// 下沉调整最大堆
downAdjust(array, 0, i);
public static void main(String[] args)
int[] arr = new int[] 1,3,2,6,5,7,8,9,10,0;
heapSort(arr);
System.out.println(Arrays.toString(arr));
桶排序
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
public class BucketSort
public static double[] bucketSort(double[] array)
//1.得到数列的最大值和最小值,并算出差值d
double max = array[0];
double min = array[0];
for(int i=1; i<array.length; i++)
if(array[i] > max)
max = array[i];
if(array[i] < min)
min = array[i];
double d = max - min;
//2.初始化桶
int bucketNum = array.length;
ArrayList<LinkedList<Double>> bucketList = new ArrayList<LinkedList<Double>>(bucketNum);
for(int i = 0; i < bucketNum; i++)
bucketList.add(new LinkedList<Double>());
//3.遍历原始数组,将每个元素放入桶中
for(int i = 0; i < array.length; i++)
int num = (int)((array[i] - min) * (bucketNum-1) / d);
bucketList.get(num).add(array[i]);
//4.对每个桶内部进行排序
for(int i = 0; i < bucketList.size(); i++)
//JDK底层采用了归并排序或归并的优化版本
Collections.sort(bucketList.get(i));
//5.输出全部元素
double[] sortedArray = new double[array.length];
int index = 0;
for(LinkedList<Double> list : bucketList)
for(double element : list)
sortedArray[index] = element;
index++;
return sortedArray;
public static void main(String[] args)
double[] array = new double[] 4.12,6.421,0.0023,3.0,2.123,8.122,4.12, 10.09;
double[] sortedArray = bucketSort(array);
System.out.println(Arrays.toString(sortedArray));
计数排序
import java.util.Arrays;
public class CountSort
public static int[] countSort(int[] array)
//1.得到数列的最大值
int max = array[0];
for(int i=1; i<array.length; i++)
if(array[i] > max)
max = array[i];
//2.根据数列最大值确定统计数组的长度
int[] countArray = new int[max+1];
//3.遍历数列,填充统计数组
for(int i=0; i<array.length; i++)
countArray[array[i]]++;
//4.遍历统计数组,输出结果
int index = 0;
int[] sortedArray = new int[array.length];
for(int i=0; i<countArray.length; i++)
for(int j=0; j<countArray[i]; j++)
sortedArray[index++] = i;
return sortedArray;
public static int[] countSortV2(int[] array)
//1.得到数列的最大值和最小值,并算出差值d
int max = array[0];
int min = array[0];
for(int i=1; i<array.length; i++)
if(array[i] > max)
max = array[i];
if(array[i] < min)
min = array[i];
int d = max - min;
//2.创建统计数组并统计对应元素个数
int[] countArray = new int[d+1];
for(int i=0; i<array.length; i++)
countArray[array[i]-min]++;
//3.统计数组做变形,后面的元素等于前面的元素之和
for(int i=1;i<countArray.length;i++)
countArray[i] += countArray[i-1];
//4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
int[] sortedArray = new int[array.length];
for(int i=array.length-1;i>=0;i--)
sortedArray[countArray[array[i]-min]-1]=array[i];
countArray[array[i]-min]--;
return sortedArray;
public static void main(String[] args)
int[] array = new int[] 4,4,6,5,3,2,8,1,7,5,6,0,10;
int[] sortedArray = countSort(array);
System.out.println(Arrays.toString(sortedArray));
array = new int[] 95,94,91,98,99,90,99,93,91,92;
sortedArray = countSort(array);
System.out.println(Arrays.toString(sortedArray));
选择排序
import java.util.Arrays;
public class SelectionSort
public static void selectionSort(int[] array)
for (int i = 0; i < array.length - 1; i++)
int minIndex = i;
for (int j = i + 1; j < array.length; j++)
if (array[j] < array[minIndex])
minIndex = j;
if (i != minIndex)
int temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
public static void main(String[] args)
int[] array = new int[] 3, 4, 2, 1, 5, 6, 7, 8, 30, 50, 1, 33, 24, 5, -4, 7, 0;
selectionSort(array);
System.out.println(Arrays.toString(array));
插入排序
import java.util.Arrays;
public class InsertionSort
public static void insertSort(int[] array)
for (int i = 1; i < array.length; i++)
int insertValue = array[i];
int j = i - 1;
//从右向左比较元素的同时,进行元素复制
for (; (j >= 0) && (insertValue < array[j]); j--)
array[j + 1] = array[j];
//insertValue的值插入适当位置
array[j + 1] = insertValue;
public static void main(String[] args)
int[] array = 12, 1, 3, 46, 5, 0, -3, 12, 35, 16 ;
insertSort(array);
System.out.println(Arrays.toString(array));
希尔排序
import java.util.Arrays;
public class ShellSort
public static void shellSort(int[] array)
//希尔排序的增量
int d = array.length;
while (d > 1)
//使用希尔增量的方式,即每次折半
d = d / 2;
for (int x = 0; x < d; x++)
for (int i = x + d; i < array.length; i = i + d)
int temp = array[i];
int j;
for (j = i - d; (j >= 0) && (array[j] > temp); j = j - d)
array[j + d] = array[j];
array[j + d] = temp;
public static void main(String[] args)
int[] array = 5, 3, 9, 12, 6, 1, 7, 2, 4, 11, 8, 10 ;
shellSort(array);
System.out.println(Arrays.toString(array));
归并排序
import java.util.Arrays;
public class MergeSort
public static void mergeSort(int[] array, int start, int end)
if (start < end)
//折半成两个小集合,分别进行递归
int mid = (start + end) / 2;
mergeSort(array, start, mid);
mergeSort(array, mid + 1, end);
//把两个有序小集合,归并成一个大集合
merge(array, start, mid, end);
private static void merge(int[] array, int start, int mid, int end)
//开辟额外大集合,设置指针
int[] tempArray = new int[end - start + 1];
int p1 = start;
int p2 = mid + 1;
int p = 0;
//比较两个小集合的元素,依次放入大集合
while ((p1 <= mid) && (p2 <= end))
if (array[p1] <= array[p2])
tempArray[p++] = array[p1++];
else
tempArray[p++] = array[p2++];
//左侧小集合还有剩余,依次放入大集合尾部
while (p1 <= mid)
tempArray[p++] = array[p1++];
//右侧小集合还有剩余,依次放入大集合尾部
while (p2 <= end)
tempArray[p++] = array[p2++];
//把大集合的元素复制回原数组
for (int i = 0; i < tempArray.length; i++)
array[i + start] = tempArray[i];
public static void main(String[] args)
int[] array = 5, 8, 6, 3, 9, 2, 1, 7 ;
mergeSort(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
基数排序
import java.util.Arrays;
public class RadixSort
//ascii码的取值范围
public static final int ASCII_RANGE = 128;
public static String[] radixSort(String[] array, int maxLength)
//排序结果数组,用于存储每一次按位排序的临时结果
String[] sortedArray = new String[array.length];
//从个位开始比较,一直比较到最高位
for (int k = maxLength - 1; k >= 0; k--)
//计数排序的过程,分成三步:
//1.创建辅助排序的统计数组,并把待排序的字符对号入座,
//这里为了代码简洁,直接使用ascii码范围作为数组长度
int[] count = new int[ASCII_RANGE];
for (int i = 0; i < array.length; i++)
int index = getCharIndex(array[i], k);
count[index]++;
//2.统计数组做变形,后面的元素等于前面的元素之和
for (int i = 1; i < count.length; i++)
count[i] = count[i] + count[i - 1];
//3.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
for (int i = array.length - 1; i >= 0; i--)
int index = getCharIndex(array[i], k);
int sortedIndex = count[index] - 1;
sortedArray[sortedIndex] = array[i];
count[index]--;
//下一轮排序需要以上一轮的排序结果为基础,因此把结果复制给array
array = sortedArray.clone();
return array;
//获取字符串第k位字符所对应的ascii码序号
private static int getCharIndex(String str, int k)
//如果字符串长度小于k,直接返回0,相当于给不存在的位置补0
if (str.length() < (k + 1))
return 0;
return str.charAt(k);
public static void main(String[] args)
String[] array = "qd", "abc", "qwe", "hhh", "a", "cws", "ope" ;
System.out.println(Arrays.toString(radixSort(array, 3)));
以上是关于《漫画算法》源码整理-5 排序算法的主要内容,如果未能解决你的问题,请参考以下文章