一、八大排序
排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程。 排序分类 总体对比
1 冒泡排序
基本思想
-
冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。 -
因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,在进行)
代码实现:
public static void bubbleSort(int[] arr){
int temp;
boolean flag = false;
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j <arr.length-1-i; j++) {
if (arr[j]>arr[j+1]){
flag = true;
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
if (!flag) {
break;
} else {
flag = false;
}
}
}
2 选择排序
基本思想
- 选择排序(select sorting)也是一种简单的排序方法。
- 它的基本思想是:第一次从arr[0]~arr[n-1] 中选取最小值,与arr[0]交换,
- 第二次从arr[1]~ arr[n-1]中选取最小值,与arr[1]交换,
- 第三次从arr[2]~ arr[n-1]中选取最小值,与arr[2]交换,…,
- 第i次从arr[i-1]~ arr[n-1]中选取最小值,与arr[i-1]交换,…,
- 第n-1次从arr[n-2]~arr[n-1]中选取最小值,与arr[n-2]交换,
总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
代码实现:
public static void selectSort(int[] arr){
int temp;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i+1; j < arr.length; j++) {
if (arr[i]>arr[j]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
3 插入排序
基本思想:
- 插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
代码实现:
public static void insertSort(int[] arr){
int temp;
for (int i = 1; i < arr.length; i++) {
int j =i;
while (j>0 && (arr[j]<arr[j-1])){
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
j--;
}
}
}
4 希尔排序
基本思想
- 希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止
代码实现
public static void shellSort2(int[] arr){
int temp;
for (int i = arr.length/2; i >0 ; i/=2) {
for (int j = i; j <arr.length ; j++) {
int k = j-i;
while (k>=0&&(arr[k]>arr[k+i])){
temp = arr[k];
arr[k] = arr[k+i];
arr[k+i] = temp;
k -=i;
}
}
}
}
5 快速排序
基本思想
- 快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
代码实现
public static void quickSort2(int[] arr,int left, int right){
if (left>right){
return;
}
int low =left;
int high = right;
int base = arr[left];
int temp;
while (low <high){
while (arr[high]>=base && low<high){
high--;
}
while (arr[low]<=base && low<high){
low++;
}
if (low<high){
temp = arr[high];
arr[high] = arr[low];
arr[low] = temp;
}
}
arr[left] = arr[low];
arr[low] = base;
quickSort2(arr,left,low-1);
quickSort2(arr,low+1,right);
}
6 归并排序
基本思想
- 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
代码实现
public static void mergeSort(int[] arr, int left, int right, int[] temp){
if (left<right){
int mid = (left+right)/2;
mergeSort(arr,left,mid,temp);
mergeSort(arr,mid+1,right,temp);
merge(arr,left, mid,right,temp);
}
}
public static void merge(int[] arr, int left, int mid, int right, int[] temp){
int i = left;
int j = mid+1;
int t = 0;
while (i<=mid && j<=right){
if (arr[i]<=arr[j]){
temp[t] = arr[i];
i++;
t++;
}else{
temp[t] = arr[j];
j++;
t++;
}
}
while (i<=mid){
temp[t] = arr[i];
i++;
t++;
}
while (j<=right){
temp[t] = arr[j];
j++;
t++;
}
int tempLeft = left;
t = 0;
while (tempLeft<=right){
arr[tempLeft] = temp[t];
tempLeft++;
t++;
}
}
}
7 基数排序
基本思想
- 将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
代码实现
public static void radixSort(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i]>max){
max = arr[i];
}
}
int maxLength = (max+"").length();
int[][] bucket = new int[10][arr.length];
int[] bucketElementCounts = new int[10];
for (int i = 0,n=1; i <maxLength ; i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j]/n%10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
int index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
if (bucketElementCounts[k]!=0){
for (int l = 0; l <bucketElementCounts[k] ; l++) {
arr[index] = bucket[k][l];
index++;
}
}
bucketElementCounts[k] = 0;
}
}
}
8 堆排序
基本思想:
- 将待排序序列构造成一个大顶堆
此时,整个序列的最大值就是堆顶的根节点。 将其与末尾元素进行交换,此时末尾就为最大值。 然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
代码实现:
public static void heapSort(int arr[]) {
int temp = 0;
System.out.println("堆排序!!");
for(int i = arr.length / 2 -1; i >=0; i--) {
adjustHeap(arr, i, arr.length);
}
for(int j = arr.length-1;j >0; j--) {
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr, 0, j);
}
}
public static void adjustHeap(int arr[], int i, int lenght) {
int temp = arr[i];
for(int k = i * 2 + 1; k < lenght; k = k * 2 + 1) {
if(k+1 < lenght && arr[k] < arr[k+1]) {
k++;
}
if(arr[k] > temp) {
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = temp;
}
二、查找
1 线性查找
public static int seqSearch(int[] arr, int value) {
for (int i = 0; i < arr.length; i++) {
if(arr[i] == value) {
return i;
}
}
return -1;
}
2 二分查找
前提条件:数组是排序好的
递归方法:
public static int binarySearch(int[] arr, int left, int right, int findVal){
if (left>right){
return -1;
}
int mid = (left+right)/2;
int midVal = arr[mid];
if (midVal>findVal){
return binarySearch(arr,left,mid-1,findVal);
}else if (midVal<findVal){
return binarySearch(arr,mid+1,right,findVal);
}else {
return mid;
}
}
非递归方法
public static int binarySearch2(int[] arr, int findVal){
int head = 0;
int end = arr.length-1;
int mid;
while (head<=end){
mid = (head+end)/2;
if (arr[mid] == findVal){
return mid;
}else if(arr[mid]>findVal){
end =mid-1;
}else {
head = mid+1;
}
}
return -1;
}
3 插值查找
代码实现
public static int insertValueSearch(int[] arr, int left, int right, int findVal) {
System.out.println("插值查找次数~~");
if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
return -1;
}
int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
int midVal = arr[mid];
if (findVal > midVal) {
return insertValueSearch(arr, mid + 1, right, findVal);
} else if (findVal < midVal) {
return insertValueSearch(arr, left, mid - 1, findVal);
} else {
return mid;
}
4 斐波那契(黄金分割法)查找
代码实现
public static int[] fib(int n){
int[] f = new int[n];
f[0] = 1;
f[1] = 1;
for (int i=2;i<20;i++){
f[i] = f[i-1] + f[i-2];
}
return f;
}
public static int fibSearch(int[] a, int key){
int low = 0;
int high = a.length-1;
int k = 0;
int mid;
int[] f = fib(20);
while (high>f[k]-1){
k++;
}
int[] temp = Arrays.copyOf(a,f[k]);
for (int i = high+1; i < temp.length; i++) {
temp[i] = a[high];
}
while (low<=high){
mid = low+ f[k-1]-1;
if (key<temp[mid]){
high = mid-1;
k--;
}else if (key>temp[mid]){
low = mid + 1;
k-=2;
}else {
if(mid<=high){
return mid;
}else {
return high;
}
}
}
return -1;
}
|