先看一下Arrays中的源代码,很有学习意义
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
/**
* Searches a range of
* the specified array of ints for the specified value using the
* binary search algorithm.
* The range must be sorted (as
* by the {@link #sort(int[], int, int)} method)
* prior to making this call. If it
* is not sorted, the results are undefined. If the range contains
* multiple elements with the specified value, there is no guarantee which
* one will be found.
*
* @param a the array to be searched
* @param fromIndex the index of the first element (inclusive) to be
* searched
* @param toIndex the index of the last element (exclusive) to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array
* within the specified range;
* otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
* <i>insertion point</i> is defined as the point at which the
* key would be inserted into the array: the index of the first
* element in the range greater than the key,
* or <tt>toIndex</tt> if all
* elements in the range are less than the specified key. Note
* that this guarantees that the return value will be >= 0 if
* and only if the key is found.
* @throws IllegalArgumentException
* if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0 or toIndex > a.length}
* @since 1.6
*/
public static int binarySearch(int[] a, int fromIndex, int toIndex,
int key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
// Like public version, but without range checks.
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
可以看到源码中的思路考虑的非常全面!
我自己的代码实现:
import java.util.ArrayList;
import java.util.Arrays;
import static java.util.Arrays.sort;
public class text02 {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
System.out.println(BR(a, 0, 3, 4));
System.out.println(non_BR(a, 0, 3, 4));
int i = Arrays.binarySearch(a, 4);
System.out.println(i);
}
//快速排序
public static void QS(int a[], int left, int right) {
if (left < right) {
int key = a[left];//哨兵
int i = left;//左指针
int j = right;//右指针
while (i < j) {
while (a[j] > key&&i<j) j--;//从右边找小于哨兵的
while (a[i] <= key&&i<j) i++;//从左边找大于哨兵的
Swap(a, i, j);
}
//当i和j重合的时候
a[left] = a[i];//a[j]也可以
a[i] = key;
QS(a, left, i - 1);
QS(a, i + 1, right);
}
}
private static void Swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
//递归实现
public static int BR(int[] a, int left, int right, int x) {
//sort(a);
QS(a, left, right);
//int mid = (left + right) / 2;
int mid = (left + right) >> 1;
if (x == a[mid]) {
return mid;
}
if (left >= right) {
return 0;
} else if (x > a[mid]) {
return BR(a, mid + 1, right, x);
} else if (x < a[mid]) {
return BR(a, left, mid - 1, x);
}
return 0;
}
//非递归实现
public static int non_BR(int a[], int left, int right, int x) {
// sort(a);
QS(a, left, right);
while (left <= right) {
int mid = (left + right) / 2;
if (a[mid] == x) {
return mid;
} else if (x > a[mid]) {
left = mid + 1;
} else if (x < a[mid]) {
right = mid - 1;
}
}
return -1;
}
}
也可以使用冒泡排序
//冒泡排序
public static void FS(int a[]) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0; j < a.length - i - 1; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
还可以使用归并排序:
1、归并排序的伪代码算法思路:
//归并排序伪代码算法思路
void MergerSort(int *a, int left, int right) {
if (left == right) return;//递归边界
if (left < right) {
int mid = (left + right)/2;
MergerSort(a, left, mid);//左递归
MergerSort(a, mid + 1, right);//右递归
Merger(a, left, mid, right);//合并
}
}
void Merger(int* a, int left, int mid, int right) {
int[] result = new int[a.length];//用于合并
int k = 0, i = left, j = mid + 1;
while (i <= mid && j <= right) {
if (a[i] < a[j]) {//如果左数组小
result[k++] = a[i++];//把元素放进合并过后的数组里
} else {//如果右数组小
result[k++] = a[j++];//把元素放进合并过后的数组里
}
}
if (i == mid + 1) {//左数组装完了
while (j <= right) result[k++] = a[j++];
} else if (j >= right) {//右数组装完了
while (i <= mid + 1) result[k++] = a[i++];
}
a=result;
}
2、归并排序的具体代码实现 :
//归并排序
public static void MergerSort(int a[], int left, int right) {
if (left == right) return;//只有一个元素
if (left < right) {
int mid = (left + right) >> 1;
MergerSort(a, left, mid);
MergerSort(a, mid + 1, right);
int[] result = Merger(a, left, mid, right);
int j = 0;
for (int i = left; i <= right; i++) {
a[i] = result[j++];
}
}
}
//相当于有序数组的合并
private static int[] Merger(int[] a, int left, int mid, int right) {
int[] result = new int[a.length];//用于合并
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
if (a[i] < a[j]) {//如果左数组小
result[k++] = a[i++];//把元素放进合并过后的数组里
} else {//如果右数组小
result[k++] = a[j++];//把元素放进合并过后的数组里
}
}
if (i == mid + 1) {//左数组装完了
while (j <= right) result[k++] = a[j++];//右数组剩余元素装入
} else if (j == right + 1) {//右数组装完了
while (i <= mid) result[k++] = a[i++];//左数组剩余元素装入
}
return result;
}
注意:result在Merge方法调用完毕后就直接被虚拟机回收了
所以不能直接a=result把result的地址赋值给a,需要在主方法MergeSort中用一个int[] 对象接受一下Merge方法的数组。
最后把新定义接受Merge方法返回值的数组的值逐一赋值给a数组!!!
冒泡排序复杂度高,归并排序利用了空间换时间的思想时间复杂度低!
最后完整的代码奉上!
import java.util.ArrayList;
import java.util.Arrays;
import static java.util.Arrays.parallelPrefix;
import static java.util.Arrays.sort;
public class text02 {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
System.out.println(BR(a, 0, 3, 4));
System.out.println(non_BR(a, 0, 3, 1));
int i = Arrays.binarySearch(a, 4);
System.out.println(i);
//快速排序、归并排序和冒泡排序的测试区
int[] b = {5, 3, 7, 2, 4, 6, 9};
/*FS(b);
Print(b);*/
try {
MergerSort(b, 0, b.length - 1);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界!");
}
// QS(b, 0, b.length - 1);
Print(b);
}
//冒泡排序
public static void FS(int a[]) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0; j < a.length - i - 1; j++) {
if (a[j] > a[j + 1]) {
Swap(a, j, j + 1);
}
}
}
}
//快速排序
public static void QS(int a[], int left, int right) {
if (left < right) {
int key = a[left];//哨兵
int i = left;
int j = right;
while (i < j) {
while (a[j] > key && i < j) j--;
while (a[i] <= key && i < j) i++;
Swap(a, i, j);
}
a[left] = a[i];
a[i] = key;
QS(a, left, i - 1);
QS(a, i + 1, right);
}
}
private static void Swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
//归并排序
public static void MergerSort(int a[], int left, int right) {
if (left == right) return;//只有一个元素
if (left < right) {
int mid = (left + right) >> 1;
MergerSort(a, left, mid);
MergerSort(a, mid + 1, right);
int[] result = Merger(a, left, mid, right);
int j = 0;
for (int i = left; i <= right; i++) {
a[i] = result[j++];
}
}
}
//想当于有序数组的合并
private static int[] Merger(int[] a, int left, int mid, int right) {
int[] result = new int[a.length];//用于合并
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
if (a[i] < a[j]) {//如果左数组小
result[k++] = a[i++];//把元素放进合并过后的数组里
} else {//如果右数组小
result[k++] = a[j++];//把元素放进合并过后的数组里
}
}
if (i == mid + 1) {//左数组装完了
while (j <= right) result[k++] = a[j++];//右数组剩余元素装入
} else if (j == right + 1) {//右数组装完了
while (i <= mid) result[k++] = a[i++];//左数组剩余元素装入
}
return result;
}
//递归实现
public static int BR(int[] a, int left, int right, int x) {
sort(a);
int mid = (left + right) / 2;
if (left > right) return 0;
if (a[mid] == x) return mid;
if (a[mid] > x) return BR(a, left, mid - 1, x);
if (a[mid] < x) return BR(a, mid + 1, right, x);
return 0;
}
//非递归实现
public static int non_BR(int a[], int left, int right, int x) {
sort(a);
while (left <= right) {
int mid = (left + right) >> 1;
if (a[mid] == x) return mid;
else if (a[mid] > x) right = mid - 1;
else if (a[mid] < x) left = mid + 1;
}
return 0;
}
//数组打印方法
public static void Print(int[] a) {
for (int j = 0; j < a.length; j++) {
if (j == 0) {
System.out.print("[" + a[j]);
} else if (j == a.length - 1) {
System.out.print("," + a[j] + "]");
} else {
System.out.print("," + a[j]);
}
}
}
}
控制台打印的结果为:
可以看到查找和排序的算法都实现了其逻辑功能!