本文所有排序均为从小到大排序,代码全部可跑通。
冒泡排序
思想:
依次比较相邻的两个数,小数在前,大数在后,每一轮最大的数都会放到数组最后。
步骤:
1、比较相邻的元素,如果第一个比第二个大,就交换。
2、对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。
3、除了最后一个元素,所有的元素重复步骤1、步骤2,排序完成。
代码:
public static void bubbleSort(int array[]){
int t = 0; //用作交换
for(int i = 0; i < array.length; i++){
//每轮相邻两个做比较,最后一个不用比
for(int j = 0; j < array.length-1; j++){
//如果前一个比后一个大,则交换
if(array[j] > array[j+1]){
t = array[j];
array[j] = array[j+1];
array[j+1] = t;
}
}
}
}
选择排序
思想:
每一轮找出最小的一个元素,与当前值交换,直到遍历结束。
步骤:
1、遍历数组,从当前值右边数组中找出一个最小值与当前值交换。
2、重复步骤1直至最后一个元素,排序完成。
代码:
public static void selectSort(int array[]){
int t = 0; //用于交换,默认第一个
for(int i = 0; i < array.length; i++){
int index = i;//存放当前值的下标
//遍历当前值右边的数组,找出最小值
for(int j = i+1; j < array.length; j++){
//找到最小值的下标
if(array[index] > array[j]) {
index = j;
}
}
//若找到本轮最小值,则与当前值交换
if(index != i){
t = array[i];
array[i] = array[index];
array[index] = t;
}
}
}
插入排序
思想:
每一步将一个待排序的数据插入到前面已经排好序的有序序列中,直到插完所有元素为止。
步骤:
1、从第二个元素开始遍历待排序数组。
2、当前元素与左边的每个元素从后到前依次进行比较。
3、若当前元素大,则不动;若当前元素小,则继续向前比较,直到遇到更小的元素时停下并插入。
4、步骤1的循环结束,数组排序完成。
代码:
public static void insertionSort(int arr[]){
//遍历
for(int i = 0; i < arr.length; i++){
//向左边找比它大的数,然后交换
//一轮循环结束后,相当于把这个数插入到合适的位置了
for(int j = i; j > 0; j--){
if(arr[j] < arr[j-1]){
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
希尔排序
思想:
插入排序的优化排序,对数组先分组,再对分组里的数组进行插入排序,使得排序时间更稳定。
步骤:
1、默认分组数量为数组长度。
2、当前分组数量除以二,作为现在分组数量。
3、对数据进行分组,如数组长度为10,那么数组就被分为五组,每组内数据长度不一定一样。
4、分别对每个分组进行插入排序。
5、重复步骤2~4,当分组数量为1时,进行最后一次插入排序,数组排序完成。
代码:
public static void shellSort(int arr[]){
for(int step = arr.length / 2; step > 0; step /= 2){
for(int i = step; i < arr.length;i++){
int value = arr[i];
int j;
for(j = i - step; j >= 0 && arr[j] > value; j -= step){
arr[j + step] = arr[j];
}
arr[j + step] = value;
}
}
}
基数排序
思想:
任何数的每个位数只有可能是0~9,也就是10个数,从个位开始到最高位结束。
步骤:
1、准备一个长度为10的二维数组,一维下标也就是0~9。
2、得到待排序数组最高位。
3、遍历数组,从个位开始截取,到最高位结束,将数字放到截取位数对应下标的二维数组中。
4、从二维数组中按顺序取出新的数组。
5、如果数字没有截取到位数,那就是已经排序好的了,循环步骤3~步骤4,直至排序完成。
代码:
public static void basicSort(int a[]){
int max = 0;
//找出最大值
for(int i = 0; i < a.length; i++){
if(a[i] > max){
max = a[i];
}
}
//找出最大位数
int times = 0;
while(max > 0){
max = max / 10;
times ++;
}
//创建9个集合,存放对应位数是0到9的数,相当于二维数组
List<ArrayList> queen = new ArrayList<>();
for(int i = 0; i < 10; i++){
ArrayList q = new ArrayList();
queen.add(q);
}
for(int i = 0; i < times; i++){
for(int j = 0; j < a.length; j++) {
//取出对应位数,x的值为0~9,放到对应list中
int x = a[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
ArrayList q = queen.get(x);
q.add(a[j]);
}
int count = 0;
for(int z = 0; z < 10; z++){
//先进先出,将list数据从小到大放到数组中
while (queen.get(z).size() > 0){
ArrayList<Integer> c = queen.get(z);
a[count] = c.get(0);
c.remove(0);
count ++;
}
}
}
}
归并排序
思想:
将一个数组从中间分开,再将左右两个数组分别排序后合并起来。通过递归,最后的两个部分就是两个数,比较大小后交换,层层向上合并即可完成排序。
步骤:
1、取得中间值下标mid
2、对mid左边右边数组分别进行步骤1,直到左边右边各一个数。
3、比较这两个数,如果右边比左边大,就交换。
4、交换完合并这两个数成为一个数组,向上层层合并。
代码:
public static int[] mergeSort(int[] a,int low,int high){
int mid = (low + high) / 2;
if(low < high){
mergeSort(a,low,mid);
mergeSort(a,mid + 1,high);
merge(a,low,mid,high);
}
return a;
}
public static void merge(int[] a,int low,int mid,int high){
int[] temp = new int[high - low + 1];
int i = low;
int j = mid + 1;
int k = 0;
while(i <= mid && j <= high){
if(a[i] < a[j]){
temp[k++] = a[i++];
}else{
temp[k++] = a[j++];
}
}
while (i <= mid){
temp[k++] = a[i++];
}
while(j <= high){
temp[k++] = a[j++];
}
for(int x = 0; x < temp.length; x++){
a[x+low] = temp[x];
}
}
堆排序
思想:
首先需要了解堆的概念,先做出一个大顶堆,再通过顶和底的交换完成排序。
步骤:
1、将数组构建成一个大顶堆。
2、将堆顶与末尾交换,交换后,堆顶元素变到堆底,然后从堆中取出,这个数就是整个堆中的最大值,放到存放排序结果的数组中。
3、重复步骤1和步骤2,最后堆没有了,全部存放到排序数组中,已经是排好序的了。
代码:
public static void adjustHeap(int[] a, int i, int len) {
int temp, j;
temp = a[i];
for (j = 2 * i; j < len; j *= 2) {// 沿关键字较大的孩子结点向下筛选
if (j < len && a[j] < a[j + 1])
++j; // j为关键字中较大记录的下标
if (temp >= a[j])
break;
a[i] = a[j];
i = j;
}
a[i] = temp;
}
public static void heapSort(int[] a) {
int i;
for (i = a.length / 2 - 1; i >= 0; i--) {// 构建一个大顶堆
adjustHeap(a, i, a.length - 1);
}
for (i = a.length - 1; i >= 0; i--) {// 将堆顶记录和当前未经排序子序列的最后一个记录交换
int temp = a[0];
a[0] = a[i];
a[i] = temp;
adjustHeap(a, 0, i - 1);// 将a中前i-1个记录重新调整为大顶堆
}
}
快速排序
思想:
选举一个数,使得左边都比它小,右边都比它大,重复直至排序完成。
步骤:
1、在数组中随机选一个数作A。
2、有两个指针,L,R分别指向除去A后的数组头和尾。
3、L指针向右移动,如果L指针指向的数比A大,则R指针向左移动。
4、如果R指针指向的数比A小,交换L,R两个指针所指向的数。
5、交换后,L,R指针位置不变,继续重复3、4步骤,直至LR指针重合。
6、将A与LR指针重合指向的数交换,这样不论是否有序,A左边的数都比A小,右边的数都比A大。
7、将A左边的数组,和右边的数组分别循环进行步骤1~步骤6,退出循环的条件是数组左边只有一个数。
代码:
public static void quickSort(int[] arr,int low,int high) {
int i, j, temp, t;
//全部都进行过一轮了
if (low > high) {
return;
}
//一个指针指向低位,一个指向高位
i = low;
j = high;
//temp就是标定比大小的数
temp = arr[low];
while (i < j) {
//从右往左找到比标定数小的
while (temp <= arr[j] && i < j) {
j--;
}
//从左往右找到比标定数大的
while (temp >= arr[i] && i < j) {
i++;
}
//交换这两个数
if (i < j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//左右两个指针重合了,也就是i = j了
//将标定数插入到重合位置,就是相当于交换位置
arr[low] = arr[i];
arr[i] = temp;
//这样arr[i]左边都比它小,右边都比它大
//递归调用左半数组
quickSort(arr, low, j - 1);
//递归调用右半数组
quickSort(arr, j + 1, high);
}