原始冒泡排序:两层循环,内层循环时比较前后大小判断是否需要交换位置
private static void baseBubbleSort(int[] arr) {
int temp;
int count=0;
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1; j++) {
count++;
//判断大小是否需要交换位置
if (arr[j] > arr[j + 1]) {
temp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
}
}
}
System.out.println("原始冒泡排序:"+Arrays.toString(arr));
System.out.println("原始冒泡排序次数:"+count);
}
优化冒泡排序: 在整个一轮内循环之后判断是否有交换,有交换才进行下一轮外循环,考虑用布尔值
private static void betterBubbleSort(int[] arr) {
int temp;
int count=0;
boolean flag=false;
for (int i = 0; i < arr.length-1; i++) {
//每外循环一次都要重置为false
flag=false;
for (int j = 0; j < arr.length-1; j++) {
count++;
//判断大小是否需要交换位置
if (arr[j] > arr[j + 1]) {
temp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
flag=true;
}
}
if (!flag) {
break ;
}
}
System.out.println("优化冒泡排序:"+Arrays.toString(arr));
System.out.println("优化冒泡排序次数:"+count);
}
效果截图:
选择排序:
所谓选择排序即选择一个元素当做最小(或最大)值a,然后拿后面的元素与之做比较,在每一轮比较之后找到真正的最小(最大) 值b,然后a和b做交换
private static void selectSort(int[] arr) {
int temp;
for (int i = 0; i < arr.length - 1; i++) {
//假设最小元素的索引值为i
int minIndex=i;
//一次完整的内循环之后会得到一个最小元素的索引
for (int j = i + 1; j < arr.length; j++) {
if (arr[minIndex] > arr[j]) {
//修改最小元素的索引
minIndex=j;
}
}
//将得到的最小元素与外层循环的元素交换位置
if (arr[minIndex] != arr[i]) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
System.out.println("选择排序:"+Arrays.toString(arr));
}
插入排序:
在已排好序的数组(当只有第一个元素那肯定是已排好的,后续再一个一个插入)中插入一个元素,同时插入后的数组也是有序的
private static void insertSort(int[] arr) {
int temp;
for (int i = 0; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
} else {
break;
}
}
}
System.out.println("插入排序:"+Arrays.toString(arr));
}
快速排序:核心是分置(①-⑤)和递归(⑥-⑦)
步骤:
①:选一个元素(一般第一个或者最后一个,这里选第一个)作为基数(作比较用)
②:从最后一个往前查找(j--),找到小于基数的元素就把此元素放到基数所在的位置(最开始基数实在索引为0的位置上)
③:此时的j和i的光标位置没变,只是i所在的元素值变了,然后从前往后找(i++),找到比基数大的元素,再把次位置的元素值给j所 在位置
④:此时应该是i和j光标上的值是一样的,然后就又该从j的位置往前面(j--)查找重复②③步骤,一直到i>j为止,所以整个②和③在 while(i<j)循环里
⑤:循环完成之后把基数值放在i=j的位置上,此时完成第一次排序,基数左边的元素小于基数,右边的元素大于基数
⑥:处理基数左边的元素(小于基数的元素),用递归就行,只不过要修改右边界为j-1,新的基数自然变了,这一步完成那么左边的 元素就全部排好了
⑦:处理基数右边的元素(大于基数的元素),同样用递归,修改左边界为j+1,新的基数自然产生,这一步完成右边的元素也排好了, 即整个排序完成
注意:
既然是递归调用,那就必须要有结束条件,即在外层while循环之前加上if(i>j)就return的结束条件,否则栈溢出
private static void quickSort(int[] arr, int left, int right) {
//声明递归结束条件
if (left > right) {
return;
}
//声明用于比较的基础元素-这里使用左边第一个元素
int baseElement = arr[left];
//记录左光标
int i=left;
//记录右光标
int j = right;
while (i < j) {
//定义的基础元素为左边的,则这里从右边开始往左边查询小于基础元素的元素
while (arr[j] >= baseElement && i < j) {
j--;
}
//找到比基础元素小的元素移动到左边
arr[i] = arr[j];
//然后从左边往右边查询大于基础元素的元素
while (arr[i] <= baseElement && i < j) {
i++;
}
//找到比基础元素大的元素移动到右边
arr[j] = arr[i];
}
//第一轮扫描完之后基础元素左边都小于它,右边的元素应该就大于它,并将它的位置放到中间应该的位置
arr[i] = baseElement;
//递归处理基础元素左边元素
quickSort(arr, left, j - 1);
//递归处理基础元素右边元素
quickSort(arr, left + 1, right);
}