皆以从小到大排序为例。参考自一像素(博客园)
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.每一轮④结束后,最后的元素已经为最大的,不需要再排序
选择排序
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
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
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
算法名称 | 速记 |
---|---|
冒泡排序 | 比较相邻元素,大的往后挪 |
选择排序 | 选择无序区最小值放有序区末尾 |
插入排序 | 取未排序的第一个元素,从后往前与已排序的比较,插入合适位置 |
希尔排序 | 分组,组内进行插入排序 |
归并排序 | 分成几个子序列,每个子序列分别归并排序,合并 |
快速排序 | 取一个基准,比基准小的放前面,大的放后面 |
堆排序 | 构建大顶堆,堆顶和最后一个叶子节点值交换,删除最后一个叶子节点 |
计数排序 | 统计值出现的次数,存入以值为下标的数组里,再根据值和次数排序 |
桶排序 | 把数据按照某规律放桶里,对每个桶插入排序,最后汇总 |
基数排序 | 从最低位到最高位,把数据分类放入桶中,汇总 |
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。