1.冒泡排序
1.1 实现思路
冒泡排序思想是通过将两个互相相邻的元素进行比较,如果前一个元素大于后一个元素,进行交换位置。否则不交换。外层循环控制层数,内存循环控制个数。每进行一轮都会将最大数字移动到最后,所以经过多次交换就可以实现将数组中的元素进行有序排列了。
note:我们在内存循环中加入一个判断标志 如果当前内存循环没有进行交换数据的操作 说明这个数组的元素已经是有序的 就可以退出循环操作。
1.2 动图演示
1.3 代码实现
public static void bubbleSort(int [] arr){
for (int i = 0; i < arr.length-1; i++) {
boolean flag = true;
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = false;
}
}
if (flag){
break;
}
}
}
2.选择排序
2.1 实现思路:
选择排序主要每次选择一个最小的下标值,在内层循环中找到最小值下标,循环n次找到最小值。最后将预先寻找的值与最小下标值进行交换,每次选择一个最小的。多次循环就可以将一个无序的数组转换成一个有序的数组了。
2.2 动图演示
2.3 代码实现
public static void selectSort2(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
}
3.插入排序
3.1 实现思路:
插入排序的思想是 将数组中分为已排好序 和
未拍好序两部分。第一个是已经拍好序的。所以i从1开始每次选择一个元素,插入到已排好序当中。而内层循环所作的就是找到判断当前要插入的元素应该插入的位置。如此反复执行,就可以找到应当插入的位置。
3.2 动图演示
3.3 代码实现
public static void selectSort2(int [] arr){
for (int i = 1; i < arr.length; i++) {
int value = arr[i];
int j = i-1;
for (; j >=0 ; j--) {
if (arr[j]>value){
arr[j+1] = arr[j];//care
}else {
break;
}
}
arr[j+1] = value;//care
}
}
4.归并排序
4.1 实现思路
归并排序:使用递归思想,将一个无序的数组多次分割成多个小的数组,将小的数组进行元素比较 最小的元素放在前面,反复执行就可以实现数组排序了
4.2 动图演示
4.3 代码实现
public static void mergeSorts(int[] arr) {
mergesort(arr, 0, arr.length - 1);
}
private static void mergesort(int[] arr, int p, int r) {
if (p >= r) return;
int q = p + (r - p) / 2;
//合并左边
mergesort(arr, p, q);
//合并右边
mergesort(arr, q + 1, r);
merge(arr, p, q, r);
}
private static void merge(int[] arr, int p, int q, int r) {
int i = p;
int j = q + 1;
int count = 0;
//定义一个数组
int[] tmp = new int[r - p + 1];
//合并两个数组
while (i <=q && j<=r) {
if (arr[i] < arr[j]) {
tmp[count++] = arr[i++];
} else {
tmp[count++] = arr[j++];
}
}
int start = i;
int end = q;
if (j <= r) {//注意边界条件
start = j;
end = r;
}
//转移剩余的元素
while (start <= end) {
tmp[count++] = arr[start++];
}
//回归arr
for (int k = 0; k <= (r - p); k++) {
arr[p+k] = tmp[k];
}
}
4.4 简洁版
private static void mergeSort(int[] array, int left, int right) {
//条件判断
if (right <= left) {
return;
}
//中间下标位置
int mid = (left + right) >> 1;
//左边排序
mergeSort(array, left, mid);
//右边排序
mergeSort(array, mid + 1, right);
//合并
merge(array, left, mid, right);
}
private static void merge(int[] array, int left, int mid, int right) {
//临时数组
int[] temp = new int[right - left + 1];
int i = left, j = mid + 1, p = 0;
//比较大小 后存储
while (i <= mid && j <= right) {
temp[p++] = array[i] <= array[j] ? array[i++] : array[j++];
}
//剩余的存储
while (i <= mid) {
temp[p++] = array[i++];
}
while (j <= right) {
temp[p++] = array[j++];
}
//赋值给原来的数组
for (int k = 0; k < temp.length; k++) {
array[left + k] = temp[k]; //care
}
}
5.快速排序
5.1 实现思路
如果要在排序数组中下标从p到r之间的一组数据,我们选择p到r之间的任意一个数据作为一个piovt(分区点),我们遍历p到r之间的数据,将小于piovt的放到左边,将大于piovt的放到右边,将piovt放到中间,经过这一步骤之后,数组p到r之间的数据就被分成了三部分,前面是p到q-1之间是小于piovt,中间是piovt
后面的q+1到r之间的是大于piovt。
5.2 动图演示
5.3 代码实现
private static void quickSort(int[] arr, int start, int end) {
if(end <= start){
return;
}
int piovt = partition(arr,start,end);//获取到piovt下标
quickSort(arr,start,piovt-1);
quickSort(arr,piovt+1,end);
}
private static int partition(int[] arr, int start, int end) {
//piovt 标杆位置, counter 小于piovt的元素的个数
int piovt = end;
int counter = start;
for (int i = start; i < end; i++) {
if (arr[i]<arr[piovt]){ //如果小于Arr[piovt] 移动到piovt前面 否则不动
int temp = arr[counter];
arr[counter] = arr[i];
arr[i] = temp;
counter++;
}
}
int temp = arr[piovt];
arr[piovt] = arr[counter];
arr[counter] = temp;
return counter;
}