博客
关于我
算法——十大排序算法(java版本实现)
阅读量:368 次
发布时间:2019-03-04

本文共 12492 字,大约阅读时间需要 41 分钟。

十大排序算法

十大排序算法脑图:

排序算法

在这里插入图片描述

冒泡排序

传统的冒泡排序

public static void sort(int array[]) {       for (int i = 0; i < array.length - 1; i++) {           for (int j = 0; j < array.length - i - 1; j++) {               int temp = 0;            if (array[j] > array[j + 1]) {                   temp = array[j];                array[j] = array[j + 1];                array[j + 1] = temp;            }        }        if (isSorted){               break;        }    }}

优化一:

问题:经过多轮排序后,数列已经有序了,剩下的几轮排序就不必执行了,可以提前结束

解决:判断数列是否已经有序,并做出标记
如果本轮排序中有元素交换,则说明数列无序,如果没有元素交换,则说明数列已经有序,直接跳出大循环。

public static void sort(int array[]) {       for (int i = 0; i < array.length - 1; i++) {           //有序标记,每一轮的初始值都是true        boolean isSorted = true;        for (int j = 0; j < array.length - i - 1; j++) {               int temp = 0;            if (array[j] > array[j + 1]) {                   temp = array[j];                array[j] = array[j + 1];                array[j + 1] = temp;                //因为有元素进行交换,所以不是有序的,标记变为false                isSorted = false;            }        }        if (isSorted){               break;        }    }}

优化二:

问题:后半部分元素中的最小值大于前半部分元素的最大值,即右边的许多元素已经有序了

解决:对数列有序区的界定
每一轮排序后,记录下来最后一次元素交换的位置,该位置即为无序数列的边界,再往后就是有序区了

public static void sort_2(int array[]) {       for (int i = 0; i < array.length - 1; i++) {           //有序标记,每一轮的初始值都是true        boolean isSorted = true;        //无序数列的边界,每次比较只需要比到这里为止        int sortBorder = array.length -1;        for (int j = 0; j < sortBorder; j++) {               int temp = 0;            if (array[j] > array[j + 1]) {                   temp = array[j];                array[j] = array[j + 1];                array[j + 1] = temp;                //因为有元素进行交换,所以不是有序的,标记变为false                isSorted = false;                //把无序数列的边界更新为最后一次交换元素位置                sortBorder = j;            }        }        if (isSorted){               break;        }    }}

参考链接:

鸡尾酒排序

参考链接:

选择排序

public class select_sort {       public static void selctionSort(int[] arr){           if (arr == null || arr.length < 2){               return;        }        for (int i = 0; i < arr.length; i++) {               int minIndex = i;            for (int j = i + 1; j < arr.length; j++) {                   minIndex = arr[j] < arr[minIndex] ? j : minIndex;            }            swap(arr,i,minIndex);        }    }    public static void swap(int[] arr,int i,int j){   /*        arr[i] = arr[i] ^ arr[j];        arr[j] = arr[i] ^ arr[j];        arr[i] = arr[i] ^ arr[j];*/        int temp = arr[i];        arr[i] = arr[j];        arr[j] = temp;    }}

插入排序

/** *  插入排序 *  一堆有序的扑克牌,插入一张牌 */public class Insert_Sort {       public static void insertionSort(int[] arr){           if (arr == null || arr.length < 2){               return;        }        for (int i = 1; i < arr.length; i++) {               for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {                   swap(arr,j,j+1);            }        }    }    public static void swap(int[] arr,int i,int j){           int temp = arr[i];        arr[i] = arr[j];        arr[j] = temp;    }}

希尔排序-x

在这里插入代码片

快速排序

在这里插入图片描述

递归实现–双边循环法、单边循环法

package sort;/** * Copyright (C), 2019-2020 * author  candy_chen * date   2020/7/3 10:50 * version 1.0 * Description: 快速排序 * * partition()  分治法(双边循环法) * partitionV2()  分治法(单边循环法) */import java.util.Arrays;import java.util.HashMap;import java.util.Map;import java.util.Stack;/** * */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);    }    /**     * 非递归实现快排     * 转换成栈的实现,在栈中存储每一次方法调用的参数     * 该方法引入一个存储Map类型元素的栈,用于存储每一次交换时的起始下标和结束下标     * 每一次循环,都会让栈顶元素出栈,通过partition方法进行分治,并且按照基准元素的位置分成左右两部分,左右两部分再分别入栈。     * 当栈位空时,说明排序完毕,退出循环。     */    public static void quickSort_(int[] arr,int startIndex,int endIndex){           //用一个集合栈来代替递归的函数栈        Stack
> quickSortStack = new Stack
>(); //整个数列的起止下标,以哈希的形式入栈 Map rootParam = new HashMap(); rootParam.put("startIndex",startIndex); rootParam.put("endIndex",endIndex); quickSortStack.push(rootParam); //循环结束条件:栈为空时 while (!quickSortStack.isEmpty()){ //栈顶元素出栈,得到起止下标 Map
param = quickSortStack.pop(); //得到基准元素位置 int pivotIndex = partition(arr,param.get("startIndex"),param.get("endIndex")); //根据基准元素分成两部分,把每一部分的起止下标入栈 if (param.get("startIndex") < pivotIndex -1){ Map
leftParam = new HashMap
(); leftParam.put("startIndex",param.get("startIndex")); leftParam.put("endIndex",pivotIndex-1); quickSortStack.push(leftParam); } if (pivotIndex +1 < param.get("endIndex")){ Map
rightParam = new HashMap
(); rightParam.put("startIndex",pivotIndex +1); rightParam.put("endIndex",param.get("endIndex")); quickSortStack.push(rightParam); } } } /** * partition方法实现了元素的交换,让数列中的元素依据自身大小,分别交换到基准元素的左右两边 * 分治 (双边循环法) * @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
pivot){ right--; } //控制left指针比较并右移 while (left

非递归实现快速排序-x

在这里插入代码片

参考链接:

归并排序

package basic_class_01;import java.util.Arrays;public class Code_05_MergeSort {   	public static void mergeSort(int[] arr) {   		if (arr == null || arr.length < 2) {   			return;		}		mergeSort(arr, 0, arr.length - 1);	}	public static void mergeSort(int[] arr, int l, int r) {   		if (l == r) {   			return;		}		int mid = l + ((r - l) >> 1);		mergeSort(arr, l, mid);		mergeSort(arr, mid + 1, r);		merge(arr, l, mid, r);	}	public static void merge(int[] arr, int l, int m, int r) {   		int[] help = new int[r - l + 1];		int i = 0;		int p1 = l;		int p2 = m + 1;		while (p1 <= m && p2 <= r) {   			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];		}		while (p1 <= m) {   			help[i++] = arr[p1++];		}		while (p2 <= r) {   			help[i++] = arr[p2++];		}		for (i = 0; i < help.length; i++) {   			arr[l + i] = help[i];		}	}	// for test	public static void comparator(int[] arr) {   		Arrays.sort(arr);	}	// for test	public static int[] generateRandomArray(int maxSize, int maxValue) {   		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];		for (int i = 0; i < arr.length; i++) {   			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());		}		return arr;	}	// for test	public static int[] copyArray(int[] arr) {   		if (arr == null) {   			return null;		}		int[] res = new int[arr.length];		for (int i = 0; i < arr.length; i++) {   			res[i] = arr[i];		}		return res;	}	// for test	public static boolean isEqual(int[] arr1, int[] arr2) {   		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {   			return false;		}		if (arr1 == null && arr2 == null) {   			return true;		}		if (arr1.length != arr2.length) {   			return false;		}		for (int i = 0; i < arr1.length; i++) {   			if (arr1[i] != arr2[i]) {   				return false;			}		}		return true;	}	// for test	public static void printArray(int[] arr) {   		if (arr == null) {   			return;		}		for (int i = 0; i < arr.length; i++) {   			System.out.print(arr[i] + " ");		}		System.out.println();	}	// for test	public static void main(String[] args) {   		int testTime = 500000;		int maxSize = 100;		int maxValue = 100;		boolean succeed = true;		for (int i = 0; i < testTime; i++) {   			int[] arr1 = generateRandomArray(maxSize, maxValue);			int[] arr2 = copyArray(arr1);			mergeSort(arr1);			comparator(arr2);			if (!isEqual(arr1, arr2)) {   				succeed = false;				printArray(arr1);				printArray(arr2);				break;			}		}		System.out.println(succeed ? "Nice!" : "Fucking fucked!");		int[] arr = generateRandomArray(maxSize, maxValue);		printArray(arr);		mergeSort(arr);		printArray(arr);	}}
public class mergeSort {       public static void mergeSort(int[] array,int left,int right){           if (right <= left) return;        int mid = (left + right) >> 1;//  (left + right) / 2        mergeSort(array, left, mid);        mergeSort(array,mid + 1,right);        merge(array,left,mid,right);    }    private static void merge(int[] arr, int left, int mid, int right) {           int[] temp = new int[right - left + 1];        int i = left,j = mid + 1,k = 0;        //两个数组要合并在一起的数组        while (i <= mid && j <= right){               temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];        }        while (i <= mid) temp[k++] = arr[i++];        while (j <= right) temp[k++] = arr[j++];        for (int p = 0; p < temp.length; p++) {               arr[left + p] = temp[p];        }        //也可以用System.arraycopy(a,start1,b,start2,length)    }}

堆排序

public class heapSort {       static void heapify(int[] array,int length,int i){           int left = 2 * i + 1,right = 2 * i + 2;        int largest = i;        if (left < length && array[left] > array[largest]) {               largest = left;        }        if (right < length && array[right] > array[largest]) {               largest = right;        }        if (largest != i){               int temp = array[i];            array[i] = array[largest];            array[largest] = temp;            heapify(array, length,largest);        }    }    public static void heapSort(int[] array){           if (array.length == 0) return;        int length = array.length;        for (int i = length / 2 - 1;i >= 0; i--) {               heapify(array,length,i);        }        for (int i = length - 1; i >= 0;i--){               int temp = array[0];            array[0] = array[i];            array[i] = temp;            heapify(array,i,0);        }    }}

参考链接:

计数排序

传统的计数排序

1.先得到数列的最大值;

2.根据数列最大值确定统计数组的长度,数组长度为:输入数列的最大值+1;
3.遍历数列,填充统计数组;
4. 遍历统计数组,输出结果

public static int[] countSort(int[] array) {       //1.得到数列的最大值    int max = array[0];    for (int i = 0; i < array.length; i++) {           if (array[i] > max) {               max = array[i];        }    }    //2.根据数列最大值确定统计数组的长度    int[] countArray = new int[array.length];    //3.遍历数列,填充统计数组    for (int i = 0; i < array.length; i++) {           countArray[array[i]]++;//每一个整数按照其值对号入座,同时对应数组下标的元素进行加1操作    }    //4.遍历统计数组,输出结果    int index = 0;    int[] sortedArray = new int[array.length];    for (int i = 0; i < array.length; i++) {           for (int j = 0; j < countArray[i]; j++) {               sortedArray[index++] = i;        }    }    return sortedArray;}

计数排序优化

问题:最大数和最小数相差较小的时候,用最大值决定统计数组的长度容易浪费空间

解决

  1. 数组的长度为数列最大值-最小值+1
  2. 数列的最小值作为一个偏移量,用于计算整数在统计数组中的下标
public static int[] countSort2(int[] array){       //1.得到数列的最大值和最小值,并计算出差值d    int max = array[0];    int min = array[0];    for (int i=0;i
max){ max = array[i]; } if (array[i]
=0;i--){ /* * 先找到统计数组中下标为 * */ sortedArray[countArray[array[i] - min] -1] = array[i]; countArray[array[i] - min]--; } return sortedArray;}

参考链接:

桶排序

桶排序:每一个桶代表的一个区间范围,可以承载一个或对个元素

桶的数量
桶的区间跨度

package sort;/** * Copyright (C), 2019-2020 * author  candy_chen * date   2020/7/13 19:03 * version 1.0 * Description: 测试 */import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.LinkedList;/** *桶排序 * 所有的桶都保存在ArrayList集合中,每一个桶都被定义成一个链表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
max){ max = array[i]; } if (array[i]
> bucketList = new ArrayList
>(bucketNum); for (int i = 0 ;i
()); } //3.遍历初始数组,将每个元素放入桶中 for (int i = 0;i
linkedList: bucketList){ for (double element:linkedList) { sortedArray[index] = element; index++; } } return sortedArray; } public static void main(String[] args) { double[] array = new double[]{ 4.12,6.421,0.0023,2.123,8.122,4.12,10.09}; double[] sortedArray = bucketSort(array); System.out.println(Arrays.toString(sortedArray)); }}

参考链接:

基数排序-x

在这里插入代码片

说明:根据网络资料进行搜索学习理解整理 若有侵权联系作者

转载地址:http://euer.baihongyu.com/

你可能感兴趣的文章
MySQL Error Handling in Stored Procedures---转载
查看>>
MVC 区域功能
查看>>
MySQL FEDERATED 提示
查看>>
mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
查看>>
Mysql group by
查看>>
MySQL I 有福啦,窗口函数大大提高了取数的效率!
查看>>
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
MySQL InnoDB 三大文件日志,看完秒懂
查看>>
Mysql InnoDB 数据更新导致锁表
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>
mysql InnoDB数据存储引擎 的B+树索引原理
查看>>
mysql innodb通过使用mvcc来实现可重复读
查看>>