排序演示链接:http://www.atool9.com/sort.php
冒泡排序,直接插入排序,快速排序,希尔排序,选择排序,归并排序,基数排序,用队列实现基数排序
冒泡排序
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端。
代码实现:
package com.test;
import java.util.Arrays;
public class test {
public static void main(String[] args) {
int[] arr = {1,4,6,8,3,10,2,6,8,9};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void bubbleSort(int[] arr){
for (int i = 0;i<arr.length-1;i++){
for (int j = 0;j<arr.length-i-1;j++){
if (arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
}
}
直接插入排序
插入排序基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入排序的基本思想是:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
代码实现:
public static void main(String[] args) {
//插入排序
int[] arr = new int[]{5,8,1,3,6,4,9};
insertSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void insertSort(int[] arr){
//遍历所有的数字
for(int i=1;i<arr.length;i++){
//如果当前数字比前一个数字小
if (arr[i]<arr[i-1]){
int temp = arr[i];
int j;
//遍历当前数字前面所有的数字
for (j=i-1;j>=0&&temp<arr[j];j--){
//把前一个数字赋给后一个数字
arr[j+1] = arr[j];
}
//把临时变量(外层for循环的当前元素)赋给不满足条件的后一个元素
arr[j+1] = temp;
}
}
}
快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
代码实现:
public static void main(String[] args) {
//快速排序
int[] arr = new int[]{5,8,1,3,6,4,9};
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr,int start,int end){
if (start < end){
//把数组中的第0个数字作为标准
int startNum = arr[start];
//记录需要排序的下标
int low = start;
int high = end;
//循环找比标准数大的数和比标准数小的数
while (low<high){
//如果右边的数字比标准数大,则向前移
while (low<high && startNum<=arr[high]){
high--;
}
//使用右边的数字替代左边的数字
arr[low] = arr[high];
//如果左边的数字比标准数小
while (low<high && arr[low]<=startNum){
low++;
}
//使用左边的数字替代高的部分
arr[high] = arr[low];
}
//把标准数赋给低的所在位置
arr[low] =startNum;
//处理所有小的数字
quickSort(arr,start,low);
//处理大的数字
quickSort(arr,low+1,end);
}
}
public static void sort(int[] arr,int start,int end){
if(start<end){
int startNum = arr[start];
int low = start;
int high = end;
while(low<high){
while(startNum<=arr[high] && low<high){
high--;
}
while(startNum>=arr[low] && low<high){
low++;
}
if(low<high){
int temp = arr[low];
arr[low]=arr[high];
arr[high]=temp;
}
}
arr[start] = arr[low];
arr[low] = startNum;
sort(arr,start,low);
sort(arr,low+1,end);
}
}
希尔排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
代码实现:
public static void main(String[] args) {
//希尔排序
int[] arr = new int[]{5,8,1,3,6,4,9};
ShellSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void ShellSort(int[] arr){
int k = 1;
//遍历所有的步长
for (int d = arr.length/2;d>0;d/=2){
//遍历所有的元素
for (int i = d;i<arr.length;i++){
//遍历本组中所有的元素
for(int j=i-d;j>=0;j-=d){
//如果当前元素大于加上步长后的那个元素
if (arr[j]>arr[j+d]){
int temp = arr[j];
arr[j] = arr[j+d];
arr[j+d] = temp;
}
}
}
System.out.println("第"+k+"次遍历结果为:"+Arrays.toString(arr));
k++;
}
}
选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
代码实现:
public static void main(String[] args) {
//选择排序
int[] arr = new int[]{5,8,1,3,6,4,9};
selectSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void selectSort(int[] arr){
//遍历所有的数
for (int i=0;i<arr.length;i++){
int minIndex = i;
//把当前遍历的数和后面所有的数进行比较,并记录最小的数的下标
for (int j=i+1;j<arr.length;j++){
//如果后面的数更小
if (arr[minIndex]>arr[j]){
//记录最小的数的下标
minIndex = j;
}
}
//如果最小的数和当前遍历数的下标不一致,说明下标为minIndex的数比当前遍历的数更小
if (i != minIndex){
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
代码实现:
public static void main(String[] args) {
int[] arr = new int[]{3,5,7,9,1,4,0,3,8};
mergeSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void mergeSort(int[] arr,int low,int high){
int middle=(high+low)/2;
if (low<high){
mergeSort(arr,low,middle);
mergeSort(arr,middle+1,high);
merge(arr,low,middle,high);
}
}
public static void merge(int[] arr,int low,int middle,int high){
//用于存储归并后的临时数组
int[] temp = new int[high-low+1];
//用于记录第一个数组中需要遍历的下标
int i = low;
//用于记录第二个数组中需要遍历的下标
int j = middle+1;
//用于记录在临时数组中存放的下标
int index = 0;
//循环遍历两个数组,取出小的数字放入temp中
while (i<=middle&&j<=high){
if (arr[i]<=arr[j]){
//第一个数组的数据更小,把小的数据放入临时数组中,让下标右移一位
temp[index] = arr[i];
i++;
}else{
temp[index] = arr[j];
j++;
}
index++;
}
//处理多余的数据
while (j<=high){
temp[index] = arr[j];
j++;
index++;
}
while (i<=middle){
temp[index] = arr[i];
i++;
index++;
}
//把临时数组中的数据重新存入原数组
for (int k = 0;k<temp.length;k++){
arr[k+low] = temp[k];
}
}
基数排序
适合位数不一致的数组排序,排的次数等于最大数的位数
代码实现:
public static void main(String[] args) {
int[] arr = new int[]{345,52,7,9907,12,4,120,13,238};
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void radixSort(int[] arr){
//存数组中最大的数,决定排序次数
int max =Integer.MIN_VALUE;
for (int i = 0;i<arr.length;i++){
if (arr[i]>max){
max=arr[i];
}
}
//求最大数组的位数,即排序次数
int count = (max+"").length();
//用于临时存储数据的数组
int[][] temp = new int[10][arr.length];
//用于记录在相应的数组中存放的数字的数量
int[] counts = new int[10];
for (int i = 0,n=1;i<count;i++,n*=10){
for (int j = 0;j<arr.length;j++){
//计算余数
int ys = arr[j] / n % 10;
//把当前遍历的数字放到指定的数组中
temp[ys][counts[ys]] = arr[j];
//记录数量
counts[ys]++;
}
//记录取的元素的下标
int index = 0;
//取出数字
for (int k = 0;k<counts.length;k++){
//记录数量不为0的话取值
if (counts[k] != 0){
for (int m = 0;m<counts[k];m++){
//取出元素
arr[index] = temp[k][m];
index++;
}
//置空数量
counts[k] = 0;
}
}
}
}
用队列实现基数排序
队列代码实现:
package com.test;
public class MyQueue {
int[] elements;
public MyQueue(){
elements = new int[0];
}
//入队
public void add(int element){
//创建一个数组
int[] newArr = new int[elements.length+1];
//把原数组中的元素复制到新数组中
for (int i = 0;i<elements.length;i++){
newArr[i] = elements[i];
}
//把添加的元素放入新数组中
newArr[elements.length] = element;
elements = newArr;
}
//出队
public int pull(){
//把数组中的第0个元素取出
int element = elements[0];
//取出一个新的数组
int[] newArr = new int[elements.length-1];
//复制原数组中的元素到新数组中
for (int i = 0;i<newArr.length;i++){
newArr[i] = elements[i+1];
}
//替换数组
elements=newArr;
return element;
}
//判断队列是否为空
public boolean isEmpty() {
return elements.length==0;
}
}
用队列实现的基数排序代码实现:
public static void main(String[] args) {
int[] arr = new int[]{345,52,7,9907,12,4,120,13,238};
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void radixSort(int[] arr){
//存数组中最大的数,决定排序次数
int max =Integer.MIN_VALUE;
for (int i = 0;i<arr.length;i++){
if (arr[i]>max){
max=arr[i];
}
}
//求最大数组的位数,即排序次数
int count = (max+"").length();
//用于临时存储数据的队列
MyQueue[] temp = new MyQueue[10];
//为队列数组赋值
for (int t = 0;t<temp.length;t++){
temp[t] = new MyQueue();
}
for (int i = 0,n=1;i<count;i++,n*=10){
for (int j = 0;j<arr.length;j++){
//计算余数
int ys = arr[j] / n % 10;
//把当前遍历的数字放到指定的队列中
temp[ys].add(arr[j]);
}
//记录取的元素的下标
int index = 0;
//取出所有队列中的数字
for (int k = 0;k<temp.length;k++){
//当前遍历的队列不为空,取值
while (!temp[k].isEmpty()){
//取出元素
arr[index] = temp[k].pull();
index++;
}
}
}
}