数组常见的排序算法
一. Arrays.sort(数组) (默认从小到大排序)
1.代码
public class MainActivity3 extends AppCompatActivity {
private int[] arrays = new int[]{1, 23, 2, 32, 1, 0, 10, 100};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
for (int i : arrays) {
Log.d("TAG", "排序前数组:" + i);
}
nativeMethod();
}
/**
* 系统方法排序
*/
private void nativeMethod() {
Arrays.sort(arrays);
for (int i : arrays) {
Log.d("TAG", "Arrays.sort方法排序后数组:" + i);
}
}
}
2.结果
D/TAG: 排序前数组:1
D/TAG: 排序前数组:23
D/TAG: 排序前数组:2
D/TAG: 排序前数组:32
D/TAG: 排序前数组:1
D/TAG: 排序前数组:0
D/TAG: 排序前数组:10
D/TAG: 排序前数组:100
**********************************************************
D/TAG: Arrays.sort方法排序后数组:0
D/TAG: Arrays.sort方法排序后数组:1
D/TAG: Arrays.sort方法排序后数组:1
D/TAG: Arrays.sort方法排序后数组:2
D/TAG: Arrays.sort方法排序后数组:10
D/TAG: Arrays.sort方法排序后数组:23
D/TAG: Arrays.sort方法排序后数组:32
D/TAG: Arrays.sort方法排序后数组:100
要想获取倒序只需倒着遍历数组即可。
二.冒泡排序
1.思路
比较相邻的元素。如果第一个比第二个大,就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。
在这一点,最后的元素应该会是最大的数。 针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2.代码
public class MainActivity3 extends AppCompatActivity {
private int[] arrays = new int[]{1, 23, 2, 32, 1, 0, 10, 100};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
for (int i : arrays) {
Log.d("TAG", "排序前数组:" + i);
}
nativeMethod();
}
/**
* 冒泡方法排序
*/
private void nativeMethod() {
int count = arrays.length;
for (int i = 0; i < count - 1; i++) {
for (int j = i + 1; j < count; j++) {
if (arrays[j] < arrays[i]) {
int temp = arrays[i];
arrays[i] = arrays[j];
arrays[j] = temp;
}
}
}
for (int i : arrays) {
Log.d("TAG", "冒泡方法排序后数组:" + i);
}
}
}
3.结果
D/TAG: 排序前数组:1
D/TAG: 排序前数组:23
D/TAG: 排序前数组:2
D/TAG: 排序前数组:32
D/TAG: 排序前数组:1
D/TAG: 排序前数组:0
D/TAG: 排序前数组:10
D/TAG: 排序前数组:100
******************************************************
D/TAG: 冒泡方法排序后数组:0
D/TAG: 冒泡方法排序后数组:1
D/TAG: 冒泡方法排序后数组:1
D/TAG: 冒泡方法排序后数组:2
D/TAG: 冒泡方法排序后数组:10
D/TAG: 冒泡方法排序后数组:23
D/TAG: 冒泡方法排序后数组:32
D/TAG: 冒泡方法排序后数组:100
三.选择排序
1.思路
和冒泡差不多,也是两轮n-1,n 只不过冒泡排序比的是大小直接排序,选择排序先比较下标再交换数据
将数组的第一个数据作为最大或者最小的值,然后通过比较循环,输出有序的数组。
2.代码
public class MainActivity3 extends AppCompatActivity {
private int[] arrays = new int[]{1, 23, 2, 32, 1, 0, 10, 100};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
for (int i : arrays) {
Log.d("TAG", "排序前数组:" + i);
}
nativeMethod();
}
/**
* 选择方法排序
*/
private void nativeMethod() {
int count = arrays.length;
for (int i = 0; i < count - 1; i++) {
int min = i;//认定一个最小数的位置
for (int j = i + 1; j < count; j++) {
if (arrays[j] < arrays[min]) {
min = j;
}
}
if (min != i) {
int temp = arrays[i];
arrays[i] = arrays[min];
arrays[min] = temp;
}
}
for (int i : arrays) {
Log.d("TAG", "选择方法排序后数组:" + i);
}
}
}
3.结果
D/TAG: 排序前数组:1
D/TAG: 排序前数组:23
D/TAG: 排序前数组:2
D/TAG: 排序前数组:32
D/TAG: 排序前数组:1
D/TAG: 排序前数组:0
D/TAG: 排序前数组:10
D/TAG: 排序前数组:100
***********************************************************
D/TAG: 选择方法排序后数组:0
D/TAG: 选择方法排序后数组:1
D/TAG: 选择方法排序后数组:1
D/TAG: 选择方法排序后数组:2
D/TAG: 选择方法排序后数组:10
D/TAG: 选择方法排序后数组:23
D/TAG: 选择方法排序后数组:32
D/TAG: 选择方法排序后数组:100
四.快速排序
1.思路
比如 待排序的数组:1 23 2 32 1 0 10 100。
那么我们可以找一个数作为基准线 然后经过一轮排序后做到 这个基准线的左侧的数都是比这个数小的,右侧的数都是比这个数大的。为了方便我们以最左边的数为基准线。即 基准线为1。
int j=arrays.length-1 右侧开始查找的位置。
int i=0 左侧开始查找的位置。
大致的算法描述如下:
右侧的数据只要大于等于基准线 就继续向左查找。
左侧的数据只要小于等于基准线 就继续向右查找。
第一轮:
j--:100(继续) 10(继续) 0(满足) j停止-- j停止的位置是右侧0的位置 下标是5。
i++:1(继续) 23(满足) i停止++ i停止的位置是左侧23的位置 下标是1。
然后交换 i和j停止位置对应的数据 即 交换 左侧23和右侧0。 交换后的数组如下
1 0 2 32 1 23 10 100
*********************************************************************************************************
第二轮:
j继续在上次停留的位置向左查找 1(继续) 32(继续) 2(继续) 但是再向左查找的话i就不小于j了(while循环中j--的条件不满足),所以j就不会继续--向左查找。
i继续在上次停留的位置向右查找 2(继续) 但是再向右查找的话i就不小于j了(while循环中i++的条件不满足),所以i就不会继续++向由查找。
这时外部while中由于i和j大小相等 所以外部while中数组中的数据不交换 数组如下
1 0 2 32 1 23 10 100
*********************************************************************************************************
原数据:1 23 2 32 1 0 10 100
***********************************
第1轮:1 0 2 32 1 23 10 100
***********************************
第2轮:1 0 2 32 1 23 10 100
***********************************
第3轮:0 1 2 1 32 23 10 100
***********************************
第4轮:0 1 2 1 32 23 10 100
***********************************
第5轮:0 1 1 2 32 23 10 100
***********************************
第6轮:0 1 1 2 10 23 32 100
***********************************
2.代码
public class MainActivity3 extends AppCompatActivity {
private int[] arrays = new int[]{1, 23, 2, 32, 1, 0, 10, 100};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
for (int i : arrays) {
Log.d("TAG", "排序前数组:" + i);
}
quickSort(0, arrays.length - 1);
for (int result : arrays) {
Log.d("TAG", "快速排序:" + result);
}
}
/**
* 快速排序
*/
private void quickSort(int left, int right) {
if (left > right) return;
//基线 即 设定一个标准 默认最左侧
int baseLine = arrays[left];
int i = left;//左侧游标
int j = right;//右侧游标
while (i != j) {
//先看右侧
while (arrays[j] >= baseLine && i < j) {
j--;
}
//再看左侧
while (arrays[i] <= baseLine && i < j) {
i++;
}
if (i < j) {
int temp = arrays[i];
arrays[i] = arrays[j];
arrays[j] = temp;
}
}
//到这里i和j相等 即完成一轮工作 然后把i或者j位置对应的数据和基线交换
arrays[left] = arrays[i];
arrays[i] = baseLine;
//第N轮 N-1轮找到的新基线对应的位置 左侧
quickSort(left, i - 1);
//第N轮 N-1轮找到的新基线对应的位置 右侧
quickSort(i + 1, right);
}
}
3.结果
D/TAG: 排序前数组:1
D/TAG: 排序前数组:23
D/TAG: 排序前数组:2
D/TAG: 排序前数组:32
D/TAG: 排序前数组:1
D/TAG: 排序前数组:0
D/TAG: 排序前数组:10
D/TAG: 排序前数组:100
********************************************************
D/TAG: 快速排序:0
D/TAG: 快速排序:1
D/TAG: 快速排序:1
D/TAG: 快速排序:2
D/TAG: 快速排序:10
D/TAG: 快速排序:23
D/TAG: 快速排序:32
D/TAG: 快速排序:100
五.二分查找
1.思路
二分查找是指查找数组中某个元素的位置,数组必须是排好序的。
2.代码
public class MainActivity4 extends AppCompatActivity {
private int mArray1[] = new int[]{12, 0, 23, 111, 0, 24, 123, 89, 3, 4, 21};//11个元素
private int mArray2[] = new int[]{12, 0, 23, 111, 24, 123, 89, 3, 4, 21};//10个元素
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
Arrays.sort(mArray1);//先进行排序
Arrays.sort(mArray2);//先进行排序
for (int i : mArray1) {
Log.d("TAG", "mArray1排序后:" + i);
}
int position1 = dichotomyMethod(mArray1, 24);
int position2 = dichotomyMethod(mArray1, 21);
Log.d("TAG", "24在数组1中的下标:" + position1);
Log.d("TAG", "21在数组1中的下标:" + position2);
for (int i : mArray2) {
Log.d("TAG", "mArray2排序后:" + i);
}
int position3 = dichotomyMethod(mArray2, 12);
int position4 = dichotomyMethod(mArray2, 89);
Log.d("TAG", "12在数组2中的下标:" + position3);
Log.d("TAG", "89在数组2中的下标:" + position4);
}
/**
* 二分法查找 数组需要提前排好序
*
* @param arrays 要查找的数组
* @param num 要查找的元素
* @return 元素在数组中的位置
*/
private int dichotomyMethod(int[] arrays, int num) {
if (null == arrays || arrays.length <= 0) return -1;
int start = 0;//查找的开始位置
int end = arrays.length;//查找的结束位置
while (start <= end) {
int mid = (start + end) / 2;
if (arrays[mid] == num) {//中间位置恰好是要找的数据
return mid;
} else {
//前提:数组从小到大排好序了
if (arrays[mid] > num) {//中间的位置都比要找的数据大 则在前半部分查找 修改end值
end = mid - 1;
} else {//中间的位置比要找的数据下 则在后半部分查找 修改start值
start = mid + 1;
}
}
}
return -1;
}
}
3.结果
D/TAG: mArray1排序后:0
D/TAG: mArray1排序后:0
D/TAG: mArray1排序后:3
D/TAG: mArray1排序后:4
D/TAG: mArray1排序后:12
D/TAG: mArray1排序后:21
D/TAG: mArray1排序后:23
D/TAG: mArray1排序后:24
D/TAG: mArray1排序后:89
D/TAG: mArray1排序后:111
D/TAG: mArray1排序后:123
D/TAG: 24在数组1中的下标:7
D/TAG: 21在数组1中的下标:5
******************************************************************
D/TAG: mArray2排序后:0
D/TAG: mArray2排序后:3
D/TAG: mArray2排序后:4
D/TAG: mArray2排序后:12
D/TAG: mArray2排序后:21
D/TAG: mArray2排序后:23
D/TAG: mArray2排序后:24
D/TAG: mArray2排序后:89
D/TAG: mArray2排序后:111
D/TAG: mArray2排序后:123
D/TAG: 12在数组2中的下标:3
D/TAG: 89在数组2中的下标:7