十大排序算法(Java实现)

十大排序算法

皆以从小到大排序为例。参考自一像素(博客园)

  1. 冒泡排序
    重复访问要排序的数列,每两个相邻的进行比较,顺序错误则交换,直到排序完成。
    1.1算法描述:
    ①比较相邻元素,前一个比后一个大,则交换两个元素;
    ②对每一对相邻元素进行①,这样最后一个元素将会是数列的最大值;
    ③除最后一个元素,针对每个元素重复进行①②;
    ④重复①②③,直到排序完成。
    1.2代码实现
import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i<count;i++)
    		arr[i] = in.nextInt();
    	arr = BubbleSort(arr);
    }
    public static int[] BubbleSort(int[] arr) {
    	int temp;
    	for(int i = 0;i < arr.length-1;i++) {
    		for(int j = 0;j < arr.length-1-i;j++) {
    			if(arr[j] > arr[j+1]) {
    				temp = arr[j];
    				arr[j] = arr[j+1];
    				arr[j+1] = temp;
    				for(int k = 0;k < arr.length;k++)
    		    		System.out.print(arr[k]+" ");
    				System.out.print("\n");
    			}
    		}
    	}
    	return arr;
    }
}

1.3 输入输出

输入:
9
25 84 21 47 15 27 68 35 20
输出:
25 21 84 47 15 27 68 35 20
25 21 47 84 15 27 68 35 20
25 21 47 15 84 27 68 35 20
25 21 47 15 27 84 68 35 20
25 21 47 15 27 68 84 35 20
25 21 47 15 27 68 35 84 20
25 21 47 15 27 68 35 20 84
21 25 47 15 27 68 35 20 84
21 25 15 47 27 68 35 20 84
21 25 15 27 47 68 35 20 84
21 25 15 27 47 35 68 20 84
21 25 15 27 47 35 20 68 84
21 15 25 27 47 35 20 68 84
21 15 25 27 35 47 20 68 84
21 15 25 27 35 20 47 68 84
15 21 25 27 35 20 47 68 84
15 21 25 27 20 35 47 68 84
15 21 25 20 27 35 47 68 84
15 21 20 25 27 35 47 68 84
15 20 21 25 27 35 47 68 84

1.4 编码过程中犯的错误

for(int i = 0;i < arr.length ;i++) {
for(int j = 0;j < arr.length-1 ;j++) {
错误原因:
1.一个n个数列,相邻元素比较这个步骤只需要执行n-1次;
2.每一轮④结束后,最后的元素已经为最大的,不需要再排序

  1. 选择排序

    2.1. 算法描述:
    ①第1遍排序时,有序区为空,无序区为R(1…n),遍历无序区选择出最小元素,将该最小元素与无序区第一个元素交换,有序区为R(1),无序区为R(2…n);
    ②第 i 遍排序(i = 2,3…n-1)时,有序区为R(1…i-1),无序区为R(i…n),遍历无序区选择出最小元素,将该最小元素与无序区第一个元素交换,有序区为R(1…i),无序区为R(i+1…n);
    ③n-1遍排序结束,有序化完成。
    2.2 代码(Java)

import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	arr = SelectionSort (arr);
    }
    public static int[] SelectionSort(int[] arr) {
    	int temp,minIndex;
    	for(int i = 0;i < arr.length-1;i++){
    		minIndex = i;
    		for(int j = i+1; j < arr.length;j++) {
    			if(arr[minIndex] > arr[j]) {
    				minIndex = j;
    			}
    		}
    		temp = arr[i];
    		arr[i] = arr[minIndex];
    		arr[minIndex] = temp;
    		for(int k = 0 ;k < arr.length;k++)
    			System.out.print(arr[k]+" ");
    		System.out.println();
    	}
    	return arr;
    }
}

2.3 输入输出

输入:
9
25 84 21 47 15 27 68 35 20
输出:
15 84 21 47 25 27 68 35 20
15 20 21 47 25 27 68 35 84
15 20 21 47 25 27 68 35 84
15 20 21 25 47 27 68 35 84
15 20 21 25 27 47 68 35 84
15 20 21 25 27 35 68 47 84
15 20 21 25 27 35 47 68 84
15 20 21 25 27 35 47 68 84

  1. 插入排序
    取未排序的第一个元素,从后往前扫描,插入已排序数列相应位置。
    3.1算法描述
    ①初始状态:第一个元素视为已排序;
    ②第 i 次插入( i = 1…n-1)时,已排序数列为R(1…i),未排序R(i+1…n),将第 i+1 个元素依次与第j个元素(j = i…1)比较并交换位置,直到第 i+1 个元素大于或等于第 j 个元素;
    ③插入 n-1 次后,排序完成。
    3.2代码
import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	arr = InsertionSort (arr);
    }
    public static int[] InsertionSort(int[] arr) {
    	int temp;
    	for(int i = 1;i < arr.length;i++){
    		for(int j = i-1;j >= 0;j--) {
    			if(arr[j+1] < arr[j]) {
    				temp = arr[j+1];
    				arr[j+1] = arr[j];
    				arr[j] = temp;
    			}
    			else break;
    		}
    		for(int k = 0 ;k < arr.length;k++)
    			System.out.print(arr[k]+" ");
    		System.out.println();
    	}
    	return arr;
    }
}

3.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
25 84 21 47 15 27 68 35 20
21 25 84 47 15 27 68 35 20
21 25 47 84 15 27 68 35 20
15 21 25 47 84 27 68 35 20
15 21 25 27 47 84 68 35 20
15 21 25 27 47 68 84 35 20
15 21 25 27 35 47 68 84 20
15 20 21 25 27 35 47 68 84

  1. 希尔排序
    又称缩小增量排序,在插入排序基础上改进,分组插入排序,优先比较距离较远的数据。
    4.1算法描述
    ①分组:第 i 次分组,分组间隔 gap /= 2(i = 1时 gap = 数列长度 n);
    ②组内插入排序:取第 m 组(m = 1…gap),组内成员 m , m+gap…进行插入排序;
    ③重复①② 直到 gap = 0。
    4.2代码
import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	arr = ShellSort (arr);
    }
    public static int[] ShellSort(int[] arr) {
    	int gap = arr.length / 2;
    	int temp;
    	for(int sub = gap;sub > 0;sub /= 2)
    		for(int m = 0;m < sub;m++)
    			for(int i = m+sub;i < arr.length;i += sub){
    				for(int j = i-sub;j >= m;j-=sub) {
    					if(arr[j+sub] < arr[j]) {
    						temp = arr[j+sub];
    						arr[j+sub] = arr[j];
    						arr[j] = temp;
    					}
    					else break;
    				}
    				for(int k = 0 ;k < arr.length;k++)
    					System.out.print(arr[k]+" ");
    				System.out.println();
    	}
    	return arr;
    }
}

4.3输入输出

输入:
9
25 84 21 47 15 27 68 35 20
输出:
15 84 21 47 25 27 68 35 20
15 84 21 47 20 27 68 35 25
15 27 21 47 20 84 68 35 25
15 27 21 47 20 84 68 35 25
15 27 21 35 20 84 68 47 25
15 27 21 35 20 84 68 47 25
15 27 20 35 21 84 68 47 25
15 27 20 35 21 84 68 47 25
15 27 20 35 21 84 25 47 68
15 27 20 35 21 84 25 47 68
15 27 20 35 21 84 25 47 68
15 27 20 35 21 47 25 84 68
15 27 20 35 21 47 25 84 68
15 20 27 35 21 47 25 84 68
15 20 27 35 21 47 25 84 68
15 20 21 27 35 47 25 84 68
15 20 21 27 35 47 25 84 68
15 20 21 25 27 35 47 84 68
15 20 21 25 27 35 47 84 68
15 20 21 25 27 35 47 68 84

5.归并排序
把要排序的数列分为两个子序列,分别将子序列有序化,最终合并成一个有序序列。
5.1算法描述
①把长度为n的要排序的序列分成两个子序列;
②对每个子序列归并排序;
③将排序好的两个子序列合并。
5.2代码

import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	MergeSort (arr, 0, count-1);
    }
    
    public static void MergeSort(int[] arr, int start, int end) {
    	if((end-start)<1) return;
    	int middle = (end+start)/2;
    	MergeSort(arr,start, middle);
    	MergeSort(arr,middle+1,end);
    	merge(arr, start, middle, end);
    }
    
    public static void merge(int[] arr, int start, int middle, int end) {
    	if((end-start)<1) return;
    	int i=start,j=middle+1,k=0;
    	int[] result = new int[end-start+1];
    	while(i <= middle && j <= end) {
    		while(i <= middle && j <= end && arr[i] <= arr[j]) {
    			result[k++]=arr[i];
    			i++;
    		}
    		while(i <= middle && j <= end && arr[j] < arr[i]) {
    			result[k++]=arr[j];
    			j++;
    		}
    	}
    	while(i <= middle) result[k++]=arr[i++];
    	while(j <= end) result[k++]=arr[j++];
    	k=0;
    	for(int m = start;m <= end;m++) {
    		arr[m] = result[k++];
    	}
    	for(int n=0;n < arr.length;n++)
    		System.out.print(arr[n]+" ");
    	System.out.println();
    }
    
    public static void swap(int[] arr, int i, int j) {
    	int temp = arr[i];
    	arr[i] = arr[j];
    	arr[j] = temp;
    }
}

5.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
25 84 21 47 15 27 68 35 20
21 25 84 47 15 27 68 35 20
21 25 84 15 47 27 68 35 20
15 21 25 47 84 27 68 35 20
15 21 25 47 84 27 68 35 20
15 21 25 47 84 27 68 20 35
15 21 25 47 84 20 27 35 68
15 20 21 25 27 35 47 68 84

5.4编程中出现的错误

这个算法自己写了很久,发现我的递归很薄弱,以后需要多做相关的题。最开始先使用的List,出现了错误1、2,后面发现使用List没有办法显示排序过程,改成了数组,先想好再写,不要边写边想。

错误1:
List = ArrayList.subList(fromIndex, toIndex);
应为List.addAll(ArrayList.subList(fromIndex, toIndex));
因为subList方法返回的只是一个视图,是一个对源列表的映射。这意味着如果对subList返回的列表进行编辑操作,源列表也会收到影响。
对subList方法返回的列表进行添加、删除元素会抛出异常。
抛出异常

错误2:
left.addAll(arr.subList(0, middle ));
right.addAll(arr.subList(middle+1,arr.size()-1) );
应为left.addAll(arr.subList(0, middle));
right.addAll(arr.subList(middle,arr.size()));[
因为fromIndex, toIndex),左闭右开;

错误3:
int middle = (end-start) /2;
取中值应该相加除二

6.快速排序
每趟通过基准把序列分成两个子序列,此时其中一部分序列所有元素都比另一部分序列元素小,对两个子序列再递归进行快速排序。
6.1算法描述
①初始状态:选定第一个元素为基准,左指针指向第一个元素,右指针指向最后一个元素;
②右指针所指元素小于基数时,交换左右指针所指的值,否则右指针移动,进入②;
③左指针所指元素大于基数时,交换左右指针所指的值,否则左指针移动,进入③;
④左右指针重合时,交换所指的值和基数值;
⑤分别对左子序列和右子序列重复①②③,排序完成。
6.2代码
代码源于牛客网木河木

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	QuickSort (arr, 0, count-1);
    }
    
    public static void QuickSort(int[] arr, int left, int right) {
    	if(left >= right) {
    		return;
    	}
    	for(int i = 0;i < arr.length;i++)
    		System.out.print(arr[i]+" ");
    	System.out.println();
    	int middle = partition(arr, left, right);
    	QuickSort(arr, left, middle-1);
    	QuickSort(arr, middle+1, right);
    }
    
    public static int partition(int[] arr, int left, int right) {
    	if(left >= right)
    		return left;
    	int i = left;
    	int j = right;
    	int pivot = arr[left];
    	while(i < j) {
    		while(arr[j] >= pivot && i < j) j--;
    		while(arr[i] <= pivot && i < j) i++;
    		if(i < j) swap(arr, i, j);
    	}
    	arr[left] = arr[i];
    	arr[i] = pivot;
    	return i;
    }
    
    public static void swap(int[] arr,int left,int right) {
    	int temp = arr[left];
    	arr[left] = arr[right];
    	arr[right] = temp;
    }
}

6.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
25 84 21 47 15 27 68 35 20
15 20 21 25 47 27 68 35 84
15 20 21 25 47 27 68 35 84
15 20 21 25 47 27 68 35 84
15 20 21 25 35 27 47 68 84
15 20 21 25 27 35 47 68 84

7.排序
参考bilibili秒懂算法
堆:分为大顶堆和小顶堆,大顶堆的根节点是所有节点中最大的,并且所有父节点一定大于左右孩子节点,小顶堆反之。
堆排序利用堆的这个性质进行排序。
7.1算法描述
①初始状态:用要排序的数列构成一个堆;
②遍历堆的所有父节点,当孩子节点大于父节点时,交换值,直到遍历到根节点;
③交换根节点的值与最后一个叶子节点的值;
④从堆中去除最后一个叶子节点;
⑤用剩下的数字构成一个新的堆;
⑥重复②③④⑤,直到堆中无数字,最终完成排序。
7.2代码

import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	HeapSort (arr);
    }
    
    public static void HeapSort(int[] arr) {
    	for(int last = arr.length-1; last > 0; last-- )
    		BuildHeap(arr,last);
    }
    
    public static void BuildHeap(int[] arr, int last) {
    	int left, right;
    	for(int i = (last+1)/2-1;i>=0;i--) {
    		left = 2*i+1;
    		right = 2*i+2;
    		if(arr[i] < arr[right] && right <= last) swap(arr,i,right);
    		if(arr[i] < arr[left] && left <= last) swap(arr,i,left);
    	}
    	swap(arr, 0, last);
    	for(int j=0;j<arr.length;j++)
    		System.out.print(arr[j]+" ");
    	System.out.println();
    }
    
    public static void swap(int[] arr, int i, int j) {
    	int temp = arr[i];
    	arr[i] = arr[j];
    	arr[j] = temp;
    }
}

7.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
20 68 25 47 15 27 21 35 84
35 27 20 47 15 25 21 68 84
20 35 25 27 15 21 47 68 84
21 25 20 27 15 35 47 68 84
15 21 20 25 27 35 47 68 84
21 20 15 25 27 35 47 68 84
15 20 21 25 27 35 47 68 84
15 20 21 25 27 35 47 68 84

8.计数排序
对某一特定范围内的整数,将其数据转化为键存储在额外开辟的数组空间中。
8.1算法描述
①找出最大最小元素,设值为max,min;
②统计每个值为 i 的元素出现的次数(i=min…max),存入数组C的第 i 项;
③顺序访问数组,将数组的键转化为数据,通过数组的值决定数据的个数。
8.2代码

import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count, min, max;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	CountingSort (arr);
    }
    
    public static void CountingSort(int[] arr) {
    	int max = arr[0],min = arr[0];
    	for(int i=0;i<arr.length;i++){
			if(arr[i] < min)
				min = arr[i];
			else if(arr[i] > max)
				max = arr[i];
		}
    	int[] bucket = new int[max+1];
    	for(int i = 0;i < arr.length;i++) {
    		bucket[arr[i]]++;
    	}
    	int k=0;
    	for(int j = 0;j < bucket.length;j++) {
    		while(bucket[j] > 0) {
    			arr[k++] = j;
    			bucket[j]--;
    		}
    	}
    	for(int m=0;m<arr.length;m++)
    		System.out.print(arr[m]+" ");
    	System.out.println();
    }
}

8.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
15 20 21 25 27 35 47 68 84

9.排序
将数据分到有限数量的桶里,每个桶再分别排序。
9.1算法描述
①设置一个定量的数组当作空桶;
②遍历输入的数据,并把数据放到相应桶中;
③对每个不是空的桶进行插入排序(其他排序也可);
⑤顺序扫描每个非空的桶,把桶中值赋给数组,排序完成。
9.2代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	BucketSort (arr);
    }
    
    public static void BucketSort(int[] arr) {
    	Map<Integer,List<Integer>> map = new HashMap<Integer, List<Integer>>();
    	for(int p=0;p<10;p++)
    		map.put(p, new ArrayList<Integer>());
    	for(int i=0;i<arr.length;i++)
    		map.get(arr[i]/10).add(arr[i]);
    	int n=0;
    	for(int j=0;j<10;j++) {
    		if(map.get(j).size() > 0)
    			InsertionSort(map.get(j));
    		while(map.get(j).size() > 0) 
    			while(map.get(j).size() > 0)	
    			{
    				arr[n++]=map.get(j).get(0);
    				map.get(j).remove(0);
    			}
    	}
    	for(int m=0;m<arr.length;m++)
    		System.out.print(arr[m]+" ");
    	System.out.println();
    }
    
    public static void InsertionSort(List<Integer> arr) {
    	int temp;
    	for(int i = 1;i < arr.size();i++){
    		for(int j = i-1;j >= 0;j--) {
    			if(arr.get(j+1) < arr.get(j)) {
    				temp = arr.get(j+1);
    				arr.set(j+1,arr.get(j));
    				arr.set(j,temp);
    			}
    			else break;
    		}
    	}
    }
}

9.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
15 20 21 25 27 35 47 68 84

10.基数排序
低位排序后收集,再高位排序后收集,以此类推直到最高位。
10.1算法描述
①取得最大值,求位数;
②遍历原始数组,按照低位分类放入桶中;
③顺序扫描桶,从非空桶中取出值存入新数组;
④遍历新数组,按照高位分类放入桶中;
⑤顺序扫描桶,从非空桶中取出值放入新数组;
⑥以此类推,直到最高位,排序完成。
10.2代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class  Main{
    public static void main(String[] args) {
    	int count;
    	Scanner in = new Scanner(System.in);
    	count = in.nextInt();
    	int[] arr = new int[count];
    	for(int i = 0;i < count;i++)
    		arr[i] = in.nextInt();
    	RadixSort (arr);
    }
    
    public static void RadixSort(int[] arr) {
    	int max=arr[0];
    	for(int q=1;q<arr.length;q++)
    		if(arr[q] > max) max = arr[q];
    	int s=0;
    	while(max!=0) {
    		max/=10;
    		s++;
    	}
    	for(int i=0;i<s;i++)
    		Sort(arr,i);
    }
    
    public static int getIndex(int x, int y) {
    	for(int i=0;i<y;i++) {
    		x /= 10;
    	}
    	return x%10;
    }
    
    public static void Sort(int[] arr,int s) {
    	Map<Integer,List<Integer>> map = new HashMap<Integer, List<Integer>>();
    	for(int p=0;p<10;p++)
    		map.put(p, new ArrayList<Integer>());
    	for(int i=0;i<arr.length;i++)
    		map.get(getIndex(arr[i],s)).add(arr[i]);
    	int n=0;
    	for(int j=0;j<10;j++)
    		while(map.get(j).size()>0)
    			while(map.get(j).size()>0)
    			{	
    				arr[n]=map.get(j).get(0);
    				map.get(j).remove(0);
    				n++;
    			}
    	for(int y=0;y<arr.length;y++)
    		System.out.print(arr[y]+" ");
    	System.out.println();
    }
}

10.3输入输出

输入
9
25 84 21 47 15 27 68 35 20
输出
20 21 84 25 15 35 47 27 68
15 20 21 25 27 35 47 68 84

算法名称 速记
冒泡排序 比较相邻元素,大的往后挪
选择排序 选择无序区最小值放有序区末尾
插入排序 取未排序的第一个元素,从后往前与已排序的比较,插入合适位置
希尔排序 分组,组内进行插入排序
归并排序 分成几个子序列,每个子序列分别归并排序,合并
快速排序 取一个基准,比基准小的放前面,大的放后面
堆排序 构建大顶堆,堆顶和最后一个叶子节点值交换,删除最后一个叶子节点
计数排序 统计值出现的次数,存入以值为下标的数组里,再根据值和次数排序
桶排序 把数据按照某规律放桶里,对每个桶插入排序,最后汇总
基数排序 从最低位到最高位,把数据分类放入桶中,汇总

十大排序算法(Java实现)_第1张图片
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

你可能感兴趣的:(算法学习)