算法
一、排序算法
1.冒泡排序
- 每一次内循环把最大或者最小的交换到顶部,类似冒泡
- o(n*2):基本不用,太慢
- 稳定
public class Bubble {
/**
* 冒泡排序:每一次内循环把最大或者最小的交换到顶部,类似冒泡
* @param array
* @return
*/
public int[] sort(int [] array){
if(array==null|| array.length<2){
return array;
}
int temp=0;
for(int i=0;i<array.length-1;i++){
int flag=0;//符号位,如果已经有序,就退出循环
for (int j = 0; j < array.length-i-1; j++) {
if(array[j+1]<array[j]){ // <升序或者 >降序
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag=1;
}
}
if(flag == 0){
break;
}
}
return array;
}
public static void main(String[] args) {
int []array={1,2,4,3,5,9,8,7};
int[] sort=new Bubble().sort(array);
for (int n:sort) {
System.out.print(n+" ");
}
}
}
2.选择排序
- 从待排序数组中选出最大或最小的元素,放到排序起始位置,再从未排序数组中继续寻找最大(小)元素,放到已排序序列的末尾…。
- 基本不用,是最不稳定的排序方法(相同的元素在排序后次序可能改变)
- o(n*2)
public class SelectSort {
/**
* 选择排序:从待排序数组中选出最大或最小的元素,放到排序起始位置,
* 再从未排序数组中继续寻找最大(小)元素,放到已排序序列的末尾....。
* 是最不稳定的排序方法 o(n*2)
* @param array
* @return
*/
public int[] sort(int [] array){
if(array==null|| array.length<2){
return array;
}
int temp=0;
for(int i=0;i<array.length-1;i++){
int minIndex=i;//认为的最小元素下标
for (int j = i+1; j < array.length; j++) {
if(array[minIndex]>array[j]){ // <升序或者 >降序
minIndex=j;
}
}
if(minIndex != i){ //判断最小值是否是开始认为的,节省资源
temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
}
}
return array;
}
}
3.插入排序
- 第一个元素认为已经排序,取出下一个元素,在已排序序列从后往前扫描,新元素大于已排序元素就将新元素移到下一元素,如果小于就交换位置
- 样本小且基本有序的时候效率高,稳定,简单排序用插入
- o(n*2)
public class InsertSort {
/**
* 插入排序:第一个元素认为已经排序,取出下一个元素,在已排序序列从后往前扫描,新元素大于已排序元素,
* 就将新元素移到下一元素,如果小于就交换位置
* o(n*2)
* @param array
* @return
*/
public int[] sort(int [] array){
if(array==null|| array.length<2){
return array;
}
int temp=0;
for(int i=1;i<array.length;i++){
for (int j = i; j > 0 && array[j]<array[j-1]; j--) {
temp=array[j];
array[j]=array[j-1];
array[j-1]=temp;
}
}
return array;
}
public static void main(String[] args) {
int []array={1,2,4,3,5,9,8,7};
int[] sort=(new InsertSort()).sort(array);
for (int n:sort) {
System.out.print(n+" ");
}
}
}
4.希尔排序
- 首先确定间隔,按间隔插入排序一次,然后缩小间隔排序一次,最后一定有一次间隔为1需要排序一次
- 特殊的插入排序
- 间隔大的时候移动的次数少,间隔小的时候移动的距离短,就比插入排序效率高
- 不稳定,一般也不用,适用于中型排序,O(n*1.3)
第一种:
public class ShellSort {
/**
* 希尔排序:
* @param array
* @return
*/
public int[] sort(int [] array){
if(array==null|| array.length<2){
return array;
}
int h=0;
while (h <= array.length / 3){
h = h*3 + 1;
}
int temp=0;
// array.length/2 等价于 array.length >> 1 (位运算,右移n位相当于除2*n,左移为乘)
for(int gap = h ;gap>0;gap = (gap-1)/3){ //for(int gap = array.length/2 ;gap>0;gap /= 2){
for(int i=gap;i<array.length;i++){
for (int j = i; j > gap - 1; j -= gap) {
if(array[j]<array[j-gap]){
temp=array[j];
array[j]=array[j-gap];
array[j-gap]=temp;
}
}
}
}
return array;
}
public static void main(String[] args) {
int []array={1,2,4,3,5,9,8,7};
int[] sort=new ShellSort().sort(array);
for (int n:sort) {
System.out.print(n+" ");
}
}
}
5.归并排序
- 将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列
- 稳定
- Java和Python对对象的排序都是改进的归并排序(TIM Sort)(对对象的排序都需要要求稳定)
- O(n log n),代价是需要额外的内存空间。
一个数组前后以排序好,如[1,2,7,8,3,4,6,]
public int[] sort(int [] array){
if(array==null|| array.length<2){
return array;
}
int mid = array.length / 2;
int [] temp = new int[array.length];
int i=0;
int j=mid+1;
int k=0;
while (i <= mid && j<array.length){
if(array[i]<=array[j]){ //稳定,相等不会交换次序
temp[k++] = array[i++];
} else {
temp[k++] = array[j++];
}
}
while (i<=mid)
temp[k++] = array[i++];
while (j<array.length)
temp[k++] = array[j++];
return temp;
}
实现排序
public class MergeSort {
/**
* 归并排序
* 简介:将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列
* 时间复杂度为O(nlogn)
* 稳定排序方式
* @param nums 待排序数组
* @return 输出有序数组
*/
public static int[] sort(int[] nums,int low,int high){
int mid = low + (high - low)/2; //防止int+int 溢出
if(low < high){
//左边
sort(nums,low,mid);
//右边
sort(nums,mid+1,high);
//左右归并
merge(nums,low,mid,high);
}
return nums;
}
/**
* 将数组中low到high位置的数进行排序
* @param nums 待排序数组
* @param low 待排的开始位置
* @param mid 待排中间位置
* @param high 待排结束位置
*/
public static void merge(int [] nums,int low, int mid, int high){
int [] temp = new int[high - low +1];//新建排序完的数组
int i=low;//左指针
int j=mid+1;//右指针
int k=0;
while (i <= mid && j<=high){
if(nums[i]<=nums[j]){ //稳定,相等不会交换次序
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
while (i<=mid)
temp[k++] = nums[i++];
while (j<=high)
temp[k++] = nums[j++];
// 把新数组中的数覆盖nums数组
for (int k2 = 0; k2 < temp.length; k2++) {
nums[k2 + low] = temp[k2];
}
}
public static void main(String[] args) {
int []array={1,2,4,3,5,9,8,7};
int[] sort=(new MergeSort()).sort(array,0,array.length-1);
for (int n:sort) {
System.out.print(n+" ");
}
}
}
6.快速排序
- O(nlog2n),不稳定
- 认为是数量级在O(nlog2n)中性能最好
public class QuickSort {
public void quick(int[] array,int l,int r){
if(l >= r){
return ;
}
int left = l,right = r;
int pivot = array[left]; //选定最左边的数为中轴排序
while (left < right){
while (left < right && array[right]>= pivot){
right--;
}
array[left] = array[right]; // array[right] < pivot 时,放在左边
while (left < right && array[left] <= pivot){
left++;
}
array[right] = array[left]; //array[left] > pivot 时,放在右边
if(left == right){
array[left] = pivot; //排完了,把中轴放在中间
}
}
quick(array,l,left-1); //这是left和right相等了
quick(array,left+1,r);
}
public static void main(String[] args) {
int []array={1,2,4,3,5,9,8,7};
new QuickSort().quick(array,0,array.length-1);
for (int n:array) {
System.out.print(n+" ");
}
}
}
7.堆排序
二、查找算法
1.顺序查找
- 顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。
int SequenceSearch(int a[], int value) {
for(int i=0; i<a.length; i++)
if(a[i]==value)
return i;
return -1;
}
2.二分查找
- 折半查找
//二分查找、折半查找
int BinarySearch1(int a[], int value) {
int low, high, mid;
low = 0;
high = a.length - 1;
while(low<=high) {
mid = (low+high)/2;
if(a[mid]==value)
return mid;
if(a[mid]>value)
high = mid-1;
if(a[mid]<value)
low = mid+1;
}
return -1;
}
- 递归
//二叉树、递归
int BinarySearch2(int a[], int value, int low, int high) {
int mid = low+(high-low)/2;
if(a[mid]==value)
return mid;
if(a[mid]>value)
return BinarySearch2(a, value, low, mid-1);
if(a[mid]<value)
return BinarySearch2(a, value, mid+1, high);
return -1;
}
3.差值查找
//插值查找
int InsertionSearch(int a[], int value, int low, int high) {
int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);
if(a[mid]==value)
return mid;
if(a[mid]>value)
return InsertionSearch(a, value, low, mid-1);
if(a[mid]<value)
return InsertionSearch(a, value, mid+1, high);
return -1;
}