一.快速排序:
1.前言:
快速排序是一种时间复杂度为O(nlogn),空间复杂度为O(nlogn)的排序方式,相比于冒泡排序,快速排序每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。
2.实现方式:
假设这里有待排序的十个数,分别是6,1,2,7,9,3,4,5,10,8。首先在这个序列中随便找一个数作为基准数,所谓基准数就是用来将比基准数大的数字与基准数小的数字分割开来。
具体操作为:首先定义两个指针,这里分别为 i 和 j , i 负责从数组最左边开始向右遍历, j 负责从数组最右边开始向左遍历。
首先j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(i在大于基准数的地方停下,j在小于基准数的地方停下,如果i先走,最后停下跟基准数交换时,总是大于基准数的,所以需要j先走)。哨兵j一步一步地向左挪动(即j–),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。
按照这个逻辑继续下去,最终走到两个指针重合,即j把所有小于基数的数字遍历完了。
这时候将i位置的数与基数交换,就实现了基数左边的数全部小于基数,右边的全部大于基数。
此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3 1 2 5 4”,右边的序列是“9 7 10 8”。接下来还需要分别处理这两个序列。只要模拟刚才的方法分别处理6左边和右边的序列即可。
当然左右两边不是处理一次就会有序,每一次执行此方法都会确定一个基数的位置,因此需要递归n/2+1次(n表示序列含有的数字数量)。
3.代码实现
/*快速排序*/
public static void quickSort(int[] arr, int left , int right) {
if (left >= right || arr.length < 1) {
return;
}
int l = left;
int r = right;
int base = arr[l];
while (l < r) {
while (arr[r] >= base && l < r) {
r--;
}
while (arr[l] <= base && l < r) {
l++;
}
if (l < r)
{
swap(arr,l,r);
}
}
swap(arr, left, l);
quickSort(arr, left, r-1);
quickSort(arr, r+1, right);
}
二.二分查找:
1.前言:
二分查找是针对已经排序好的数组进行查找其下标的一种方式,相比于遍历整个数组,二分查找能根据需要查找数字的大小快速地找出数字所在的区间范围,因此较为快速。
2.实现方法:
假设给我们一个有序数组[1,3,6,8,12,15,19,21,66],首先我们定义两个指针low和high分别指向第一个数字1和最后一个数字66,以及一个指向中间数字的指针middle指向12。再获取用户输入的想要查找的数字x(15),首先判断x是否合理,即是否存在于这个数组如果x < low,或者 x > 66则做报错处理,如果满足low < x < high, 则继续下面的判断。先将 x 与 middle进行比较,如果比middle(12)大,则查找范围变成了15 ~ 66,此时的low就指向了15,middle就指向了[15,19,21,66]的中间数,即19。然后x再与middle进行比较,如果x比middle小,则查找范围变成了[15],high指向15,此时middle也指向15,再将x与middle进行比较,发现相等,则返回middle,即x的值为15。
3.代码实现:
/*二分查找*/
public static int binarySearch(int x, int[] arr) {
int i = 0;
int k = arr.length-1;
while (i <= k) {
int m = (i + k) / 2;
if (x == arr[m]) {
return m;
}
else if (x > arr[m]) {
i = m + 1;
}
else {
k = m - 1;
}
}
return -1;
}
三.随机生成一个指定长度和大小的数组,然后对其进行排序,再进行查找:
代码实现:
/*创建一个指定长度和最大值的无重复值的数组*/
public static int[] generateArray(int length, int max) {
HashSet<Integer> set = new HashSet<>();
int[] arr = new int[length];
/*利用HashSet不能存有重复值的特性先将创建指定长度和大小的Set集合*/
while (set.size() != 10) {
int num = (int) (Math.random()*max);
set.add(num+1);
}
/*再将Set集合的元素遍历并赋给arr数组*/
Iterator iterator = set.iterator();
int i = 0;
while (iterator.hasNext()) {
arr[i] = (int) iterator.next();
i++;
}
return arr;
}
/*快速排序*/
public static void quickSort(int[] arr, int left , int right) {
if (left >= right || arr.length < 1) {
return;
}
int l = left;
int r = right;
int base = arr[l];
while (l < r) {
while (arr[r] >= base && l < r) {
r--;
}
while (arr[l] <= base && l < r) {
l++;
}
if (l < r)
{
swap(arr,l,r);
}
}
swap(arr, left, l);
quickSort(arr, left, r-1);
quickSort(arr, r+1, right);
}
/*二分查找*/
public static int binarySearch(int x, int[] arr) {
int i = 0;
int k = arr.length-1;
while (i <= k) {
int m = (i + k) / 2;
if (x == arr[m]) {
return m;
}
else if (x > arr[m]) {
i = m + 1;
}
else {
k = m - 1;
}
}
return -1;
}
/*交换*/
public static void swap(int[] arrays,int i , int j){
int temp = arrays[i];
arrays[i] = arrays[j];
arrays[j] = temp;
}
四.程序测试;
原数组: 1 17 2 3 19 4 5 7 10 13
排序后的数组: 1 2 3 4 5 7 10 13 17 19
请输入需要查找的数字:
10
10对应的下标为:6