一.二分查找
二分查找适用于有序序列。
算法思路:
以序列的中间值作为基准值,将序列分为前后两个子序列,如果要查找的值小于中间值,则去前面的子序列查找,如果子序列大于中间值,则去后面的序列查找,重复以上,直到满足条件则查询成功,后者直到子序列不存在,查询不成功。
非递归实现:
pubic static int BinarySearch(int arr[],int temp){
int low=0;
int high=arr.length-1;
int mid=0;
if(temp<arr[low]||temp>arr[high]||low>high){
return -1;
}
while(low<=high){
mid=(low+high)/2;
if(temp<arr[mid]){
high=mid-1;
}else if(temp>arr[mid]){
low=mid+1;
}else{
return mid;
}
}
return -1;
}
递归实现:
pubic static int BinarySearch(int arr[],int temp,int low,int high){
if(temp<arr[low]||temp>arr[high]||low>high){
return -1;
}
while(low<=high){
int mid=(low+high)/2;
if(temp<arr[mid]){
return BinarySearch(arr,temp,low,mid-1);
}else if(temp>arr[mid]){
return BinarySearch(arr,temp,mid+1,high);
}else{
return mid;
}
}
return -1;
}
时间复杂度:
递归与非递归一样:O(log2N)。
空间复杂度:
递归时辅助空间是常数级别的,所以空间复杂度为O(1)。
非递归时空间复杂度为O(log2N)。
二. 冒泡排序
算法思路:
1.从第一个元素开始,比较两个相邻的元素,如果第一个元素比相邻的元素大,则交换两数。
2.对于所有相邻的元素,都进行两两比较,这样在最后的元素应该是最大的。
3.对所有元素重复以上动作,除了最后一个元素。
public void Bub(int []a){
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-1-i;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int k:a){
System.out.println(k);
}
}
时间复杂度:
最好的情况:O(N) 最坏情况:O(n^2) 平均情况:O(n^2)
空间复杂度:O(1)
稳定性:稳定
三.快速排序
算法思路:
1.以序列第一个值作为基准值,比该值小的放在左边,比该值大的放在右边。
2.对左右两边分别使用快排
public void QuickSort(int arr[],int start,int end){
int i=start;
int j=end;
if(i>=j){
return;
}
boolean flag=true; //false:左-右 true:右-左
while(i!=j){
if(arr[i]>arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
flag=(flag==true)?false:true;
}
if(flag){
j--;
}else{
i++;
}
}
i--;
j++;
QuickSort(arr,start,i);
QuickSort(arr,j,end);
}
时间复杂度:
最好的情况:O(nlogN) 平均情况:O(nlogN) 最坏情况:O(n^2)
空间复杂度:
O(nlogN)~O(n^2)
稳定性:
不稳定
四. 选择排序
算法思路:
选择序列第一个值最为最小值,将剩余值与第一个值进行比较,如果小于当前的最小值,那么就把此值设置为最小值,并放到已排列序列的末尾。
public class SEL{
public static void main(String []args){
int arr[]={6,4,15,1,5,9};
int min=0;
for(int i=0;i<arr.length;i++){
min=i;
for(int j=i+1;j<arr.length;j++){
if(arr[j]<arr[min]){
min=j;
}
}
int temp=arr[i];
arr[i]=arr[min];
arr[min]=temp;
}
for(int k:arr){
System.out.println(k);
}
}
}
时间复杂度:
最好情况:O(n^2) 最坏情况:O(n^2) 平均情况:O(n^2)
空间复杂度:
O(1)
稳定性:
不稳定
四. 插入排序
算法思路:
1.第一个元素当作已排序的值
2.取出下一个元素,在已排序的元素中从后向前扫描
3.如果已排序的元素大于取出的元素的值,那么就把取出元素放到该元素的前面
4.重复3,直到取出元素小于或等于以排序元素,就把取出元素加到已排序元素后面。
public class InsertSort{
public static void main(String[] args){
int arr[]={3,44,38,5,17,2,4,6};
int index=0;
int current=0;
for(int i=1;i<arr.lrngth;i++){
index=i-1;
current=arr[i];
while(index>=0&¤t<arr[index]){
arr[index+1]=arr[index];
index--;
}
arr[index+1]=current;
}
for(int k:arr){
System.out.println(k);
}
}
}
时间复杂度:
最好情况:O(n) 平均情况:O(n^2) 最坏情况:O(n^2)
空间复杂度:
O(1)
稳定性:
稳定
五.希尔排序
希尔排序又称缩小增量排序。
算法思路:
把序列按照步长分组,对每组序列采用直接插入排序。随着步长的逐步减小,所分成的组包含的记录越来越多,当步长的值减小到1时,整个数据合成为一组,构成一组有序记录,则完成排序。
代码:
public void shellSort(int[] arr) {
int group=arr.length/2;
while(group>=1){
// 把距离为 group 的元素编为一个组,扫描所有组
for(int i=group;i<arr.length;i++){
int j=0;
int temp=arr[i];
// 对距离为 group 的元素组进行排序
for(j=i-group;j>=0&&temp<arr[j];j=j-group){
arr[j+group]=arr[j];
}
arr[j+group]=temp;
}
group=group/2; // 减小增量
}
}