开发程序就如同make love一样,你必须小心翼翼的。因为很有可能因为你的一次致命错误而提供一生的技术支持。
排序就是:将一组无序序列按照从小到大或者从大到小的顺序排列
排序分类
排序有很多种,但是大致可分为两种:
- 比较排序
- 非比较排序
在比较排序和非比较排序中又分为很多,这里初学者掌握比较排序就好了,后期可以去研究非比较排序,所以这里只将比较排序
交换排序
交换排序顾名思义就是交换它们的值使其升(降)序排序。
冒泡排序
最近经典的排序算法,它会像水里泡泡一样慢慢变大,也是我记得最清楚的算法了。
/**
* 冒泡排序:
* 待比较的序列:4,7,2,9,6
* 第一轮 i = 0 j = 5-1-i=4 表示第一轮需要比较四次才能选出第一大大值 4<7 (7<2) 7<9 (9<6) 4 2 7 6 9 得到第一大数:9
* 第二轮 i = 1 j = 5-1-i=3 表示第二轮需要比较三次才能选出第二大的值 (4<2) 4<7 (7<6) 9 2 4 6 7 9 得到第二大数:7
* 第三轮 i = 2 j = 5-1-2=2 表示第三轮需要比较两次才能选出第三大的值 2<4 4<6 7 9 2 4 6 7 9 得到第三大数:6
* 第四轮 i = 3 j = 5-1-3=1 表示第四轮需要比较一次得到倒数第二大的值 2<4 6 7 9 2 4 6 7 9 得到倒数第二数:4
* 排序完成
* 第一层循环(一共排多少轮) 元素个数-1
* 第二层排序(每轮比较次数) 元素个数-1-轮数
*/
public void bubble() {
// 创建待排序的数组
int[] arr = {27, 48, 92, 47, 92, 48, 10, 23, 54};
int t = 0; //垃圾桶
// 外层循环-循环的轮数
for (int i = 0; i < arr.length; i++) {
// 内层循环-两两对比选出最大的数
// arr.length-1-i 的含义:将数组的长度-1-i得到的是每一轮需要比较的次数
for (int j = 0; j < arr.length - 1 - i; j++) {
// 将第j个数和j + 1相比较如果小于就交换,一轮下来选出最大的元素
if (arr[j + 1] < arr[j]) {
// 小于就交换他们的元素
t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
System.out.println(Arrays.toString(arr));
}
快速排序
快速排序,说白了就是给基准数据找其正确索引位置的过程
由于没有现成的代码只能取自他人了,这个博主写的很详细
选择排序
/**
* 选择排序:
* 待比较的序列:4,7,2,9,6
* i=轮数 min代表最小数的下标 j代表将每轮每一个元素和min最小数比较取比min还小的数
* int min = i; //表示将0给min假设第一个为最小值
* 第一轮 i=0 min=0 j=0 数组从j开始循环比较min下标的值如果小于就将j给min让min始终保持数列中最小值下标,直到j循环结束第一轮找出最小值将最小值给下标i也就是第0个
* 第二轮 i=1 min=1 j=1 循环j和min比较 得到将剩下序列的最小值将最小值给下标i也就是第1个
*/
public void select () {
// 创建待排序的数组
int[] arr = {27, 48, 92, 47, 92, 48, 10, 23, 54};
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i; j < arr.length; j++) {
if (arr[j] < arr[min]) //找到最小数
min = j; //保存最小下标的索引
}
// 此时的min就是这一轮的最小数将它给下标i就是小到大排序
int t = arr[min];
arr[min] = arr[i];
arr[i] = t;
}
System.out.println(Arrays.toString(arr));
}
插入排序
/**
* 插入排序:
*/
public void insert () {
// 创建待排序的数组
int[] arr = {27, 48, 92, 47, 92, 48, 10, 23, 54};
int current;
for (int i = 0; i < arr.length - 1; i++) {
current = arr[i + 1];
int perIndex = i;
while (perIndex >= 0 && current < arr[perIndex]) {
arr[perIndex + 1] = arr[perIndex];
perIndex--;
}
arr[perIndex + 1] = current;
}
System.out.println(Arrays.toString(arr));
}
public void insert2 () {
int [] array = {27, 48, 92, 47, 92, 48, 10, 23, 54};
// 外层循环循环 每一个数的比较次数
for(int j=0;j<array.length-1;j++) {
int temp = 0;
for (int i = 1+j; i > 0; i--) {
if (array[i] < array[i - 1]) {
temp = array[i];
array[i] = array[i - 1];
array[i - 1] = temp;
}
}
}
System.out.println(Arrays.toString(array));
}
为什么有这么多排序算法呐?这些算法他们都有他们的独到之处,
在时间复杂度和空间复杂度上各不相同,也有各自的优势。
这些算法在交换值时需要i和i-1的复杂,所以我在选择的基础上修改了下
public int[] arrSort(int a[]) {
for (int i = 0; i < a.length; i++)
for (int j = i; j < a.length; j++) {
if (a[i] > a[j]) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
return a;
}
二分查找
二分查找又叫折半查找,是排序算法的延伸,在一个数组中如果我们要找到我们需要的元素,就需要将这个数组遍历一遍才知道我们要找的元素在数组的哪个位置。而二分查找,就是将这个数组对半折叠起来查找元素。
二分查找的要素就是这个数组是个已经排序好的数组。
/**
* 折半查找:
* 最小下标:low = 0
* 最大下标:hight = 数组长度 - 1
* 中间下标:mid = (最小下标 + 最大下标) / 2
* 如果查找值等于中间值,直接返回
* 如果查找值小于中间值,在左边,将中间下标 - 1给最小下标
* 如果查找值大于中间值,在右边,将中间下标 + 1给最大下标
*
* @param a 数组
* @param value 需要查找的值
* @return
*/
public int bisearchSelect(int[] a, int value) {
a = arrSort(a);
int low = 0;
int hight = a.length - 1;
while (low <= hight) { //循环条件:最小下标 <= 最大下标
int mid = (low + hight) / 2;
System.out.println("中间值:" + mid);
if (a[mid] == value) //如果等于值就返回
return mid;
if (a[mid] < value) //
low = mid + 1;
else
hight = mid - 1;
}
return -1;
}
/* 排序 */
public int[] arrSort(int a[]) {
for (int i = 0; i < a.length; i++)
for (int j = i; j < a.length; j++) {
if (a[i] > a[j]) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
return a;
}