冒泡排序
思想:元素两两比较,大的往后放,经过一轮比较后,那么最大的元素就会出现在最后面。
图示:
代码实现:
import java.util.Arrays;
public class BubbleSortDemo {
public static void main(String[] args) {
/*
*冒泡排序:元素两两比较,大的往后放,经过一轮比较后,那么最大的元素就会出现在最后面。
* 冒泡排序(从小到大)
*
* */
int[] arr = {24,69,80,57,23};
Comparison(arr);
System.out.println(Arrays.toString(arr));
}
//crtl+alt+m抽取方法
public static void Comparison(int[] arr) {
for (int j = 0; j < arr.length - 1; j++) {//比较的趟数是数组的长度-1;
for (int i = 0; i < arr.length - 1-j; i++) {//一趟中比较的次数,数组的长度-趟数
if(arr[i]>arr[i+1]){
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
}
// //第一趟,比较了4次
// for (int i = 0; i < arr.length-1; i++) {
// if(arr[i]>arr[i+1]){
// int temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// //第二趟,比较了3次
// for (int i = 0; i < arr.length-1-1; i++) {
// if(arr[i]>arr[i+1]){
// int temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// //第三趟,比较了2次
// for (int i = 0; i < arr.length-1-1-1; i++) {
// if(arr[i]>arr[i+1]){
// int temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
// // 第四趟,比较了1次
// for (int i = 0; i < arr.length-1-1-1; i++) {
// if(arr[i]>arr[i+1]){
// int temp = arr[i];
// arr[i] = arr[i+1];
// arr[i+1] = temp;
// }
// }
}
}
代码运行结果:
[23, 24, 57, 69, 80]
选择排序
思想:每次拿一个元素,跟他后面的元素,挨个去比,小的往前放,经过一轮比较后,那么最小元素就会放在最前面去。再重复上次。
图示
代码实现:
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
/*选择排序
*选择排序:每次拿一个元素,跟他后面的元素,
*挨个去比,小的往前放,经过一轮比较后,那么最小元素就会放在最前面去
*
* */
int[] arr = {24,69,80,57,13};
tuiDao(arr);
System.out.println(Arrays.toString(arr));
}
public static void tuiDao(int[] arr) {
for (int index = 0; index < arr.length-1; index++) {
for (int i = 1 + index; i < arr.length; i++) {
if (arr[index] > arr[i]) {
int temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
}
}
}
// //第一趟,拿处在第一个元素,与后面的元素一一比较
// int index = 0;
// for (int i = 1+index; i < arr.length; i++) {
// if(arr[0]>arr[i]){
// int temp = arr[0];
// arr[0] = arr[i];
// arr[i] = temp;
// }
//
// }
// //第二趟,拿处在第二个元素,与后面的元素一一比较
// index = 1;
// for (int i = 1+index; i < arr.length; i++) {
// if(arr[1]>arr[i]){
// int temp = arr[1];
// arr[1] = arr[i];
// arr[i] = temp;
// }
//
// }
// //第三趟,拿处在第三个元素,与后面的元素一一比较
// index = 2;
// for (int i = 1+index; i < arr.length; i++) {
// if(arr[2]>arr[i]){
// int temp = arr[2];
// arr[2] = arr[i];
// arr[i] = temp;
// }
// }
// //第四趟,拿处在第四个元素,与后面的元素一一比较
// index = 2;
// for (int i = 1+index; i < arr.length; i++) {
// if(arr[2]>arr[i]){
// int temp = arr[2];
// arr[2] = arr[i];
// arr[i] = temp;
// }
// }
}
}
代码运行结果:
[13, 24, 57, 80, 69]
直接插入排序
算法思路:
直接插入排序,是一种最简单的排序方法.他的基本操作是将一个记录插入到一个长度为m 的有序表中,使之仍保持有序,从而得到一个新的长度为m+1的有序列表.假设有一组元素{k1,k2…,kn},排序开始就认为k1是一个有序序列,让k2插入上述表长为1的有序序列,使之成为一个表长为2的有序序列,然后让k3插入上述表长为2的有序序列,使之成为一个表长为3的有序序列,以此类推,最后让kn插入表长为n-1的有序序列,得到一个表长为n的有序序列。
例如:
49,38,65,97,76,13,27 原始数据
[49],38,65,97,76,13,27 从1索引开始插入
[38,49], ,65,97,76,13,27
[38,49,65] 97,76,13,27
[38,49,65,97] 76,13,27
[38,49,65,76,97]13,27
[13,27,38,49,65,76,97],27
[13,27,38,49,65,76,97]
代码实现:
import java.util.Arrays;
public class DirectInsertionSort {
public static void main(String[] args) {
//直接插入排序:将后面的元素,插入之前的一个有序列表,使之仍然保持有序
/*一个数组{24,69,80,57};
* 从第二个数开始,原数组中只有24一个,把第二个数69加入原数组,并与24比较,69大于24则不交换
* 把第三个数80加入,与原数组(即24,69)依次比较,先与69比较大了不变,再与24比较。
* 把第四个数57加入,与原数组(即24,69,80)依次比较
*
* */
int[] arr = {24,69,80,57};
tuiDao(arr);
System.out.println(Arrays.toString(arr));
}
static void tuiDao(int[] arr) {
for (int j = 1; j < arr.length; j++) {
//外部循环,b不断的加入新元素
for (int i = j; i > 0; i--) {
//里部循环,新加入的数组元素与之前的数组元素依次比较
if(arr[i]<arr[i-1]){
int temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
}
}
// for (int j = 1; j < arr.length; j++) {
// int i =j;
// while(arr[i]<arr[i-1]&&i>0){
// int temp = arr[i];
// arr[i] = arr[i-1];
// arr[i-1] = temp;
// i--;
// }
// }
}
}
代码运行结果:
[24, 57, 69, 80]
希尔排序
基本思想:先将原表按增量h(步长)分组,每个子数列按照直接插入法排序,同样。用下一个增量h/2将此数列再分为子数列,直接插入排序。直到h=1时结束。
图示
代码实现:
import java.util.Arrays;
public class HillSorting {
public static void main(String[] args) {
//希尔排序:是对直接插入排序的一种改进,选择一个合适的步长(增量),
// 然后经过一轮的插入排序让数组大致有序。
// 不断地缩小步长,进行插入排序,直至步长为一,排序结束
int[] arr = {7,2,6,9,3};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void shellSort(int[] arr) {
//首次,步长取数组的一半,步长每次缩小取一半
for (int h = arr.length/2; h > 0 ; h/=2) {
for (int i =h; i < arr.length; i++) {
for (int j = i; j >h-1;j-=h) {
if (arr[j] < arr[j - h]) {
swapValue(arr, j, j - h);
}
}
}
}
//克努特序列
//h=3*h+1
//来产生,初始值为1。 1,4,13,40,121,364
// int jianGe = 1;
// while (jianGe <= arr.length/3){
// jianGe *= 3+1;
// }
// for (int h = jianGe; h > 0 ; h = (h-1)/3) {
// for (int i =h; i < arr.length; i++) {
// for (int j = i; j >h-1;j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// }
//定义步长h为4
// int h = 4;
// for (int i =h; i < arr.length; i++) {
// for (int j = i; j >h-1;j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// h = 2;//步长为2时
// for (int i =h; i < arr.length; i++) {
// for (int j = i; j >h-1;j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// h = 1;//步长为1时
// for (int i =h; i < arr.length; i++) {
// for (int j = i; j >h-1;j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
}
private static void swapValue(int[] arr, int j, int i) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
运行的结果
[2, 3, 6, 7, 9]
快速排序
实现思路:
挖坑填数
将基准数挖出形成第一个坑。
由后向前找比他小的数,找到后挖出此数填到前一个坑中。
由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中。
再重复执行2,3两步骤
代码实现:
import java.util.Arrays;
public class Mytest {
public static void main(String[] args) {
//快速排序
int[] arr = {34,23,12,56,45,7,8,97,24,23};
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
private static void quickSort(int[] arr, int startIndex, int endIndex) {
if(startIndex < endIndex){
//找到基准数索引
int index = getIndex(arr,startIndex,endIndex);
//对左右两个分区 再进行同样的步骤 ,即是递归调用
quickSort(arr,startIndex,index);//左半边
quickSort(arr,index +1,endIndex);//右半边
}
}
private static int getIndex(int[] arr, int startIndex, int endIndex) {
int i = startIndex;
int j = endIndex;
int x = arr[i];
while(i<j ){
//由后向前找比他小的数,找到后挖出此数填到前一个坑中。
while (i<j&&arr[j]>=x){
j--;
}
if(i<j){
arr[i] = arr[j];
i++;
}
//由前向后找比他大的数,找到后挖出此数填到前一个坑中。
while (i<j&&arr[i]<x){
i++;
}
if (i < j) {
arr[j] = arr[i];
j--; //顺便让j减一下
}
}
//以上循环完毕之后,将基准数填到最后一个坑里面去
arr[i]=x;
return i;
}
}
二分查找
思路:
二分查找是一种非常高效的算法,又称之为折半查找,顾名思义就是将查找的值和数组的中间值作比较【此处就要求这个数组必须是有序的了】
如果被查找的值小于中间值,就在中间值左侧数组继续查找;如果大于中间值,就在中间值右侧数组中查找;否则中间值就是要找的元素。
图示
代码实现:
public class BinarySearch {
public static void main(String[] args) {
//二分查找
int[] arr = {10,20,30,40,50,60,70,80,90,100};
int index = findIndex(arr,80);
System.out.println(index);
//二分查找的前提是数组有序
int index1 = selectIndex(arr, 50);
System.out.println(index1);//4
}
private static int selectIndex(int[] arr, int num) {
int minIndex = 0;
int endIndex = arr.length-1;
int centerIndex = (minIndex+endIndex)/2;
while (minIndex<endIndex){
if(arr[centerIndex] == num){
return centerIndex;
}else if(num<arr[centerIndex]){
endIndex = centerIndex-1;
}else if(num>arr[centerIndex]){
minIndex = centerIndex +1;
}
centerIndex = (minIndex+endIndex)/2;
}
return -1;
}
private static int findIndex(int[] arr, int num) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == num) {
return i;
}
}
return -1;
}
}