经典算法复习
(1)二分查找算法(又叫折半查找,要求待查找的序列有序。)
每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。
public class Main{
public static void main(String[] args) {
int[] num= {1,2,3,4,5,6,7,8,9};
System.out.println(biSearch(num,9));
}
public static int biSearch(int []array,int a){
int i=0;
int j=array.length-1;
int mid;
while(i<=j){
mid=(i+j)/2;
//中间位置
if(array[mid]==a){
return mid+1;
}else if(array[mid]<a){
//向右查找
i=mid+1;
}else{
//向左查找
j=mid-1;
}
}
return -1;
}
}
(2)冒泡排序算法
比较前后相邻的二个数据,如果前面数据大于后面的数据,就将这二个数据交换。
public class Main{
public static void main(String[] args) {
int[] num= {9,6,5,4,7,6,2,1,10};
bubbleSort1(num);
for(int n:num) {
System.out.print(n+" ");
}
}
public static void bubbleSort1(int [] a){
int n=a.length;
int i, j;
for(i=0; i<n; i++){
//表示n次排序过程。
for(j=1; j<n-i; j++){
if(a[j-1] > a[j]){
//前面的数字大于后面的数字就交换 //交换a[j-1]和a[j]
int temp;
temp = a[j-1];
a[j-1] = a[j];
a[j]=temp;
}
}
}
}
}
(3)插入排序算法
所谓插入排序法,就是检查第i个数字,如果在它的左边的数字比它大,进行交换,这个动作一直继续下去,直到这个数字的左边数字比它还要小,就可以停止了。插入排序法主要的回圈有两个变数:i和j,每一次执行这个回圈,就会将第i个数字放到左边恰当的位置去。
public class Main{
public static void main(String[] args) {
int[] num= {9,6,5,4,7,6,2,1,10};
sort(num);
for(int n:num) {
System.out.print(n+" ");
}
}
public static void sort(int arr[]){
for(int i =1; i<arr.length;i++){
//插入的数
int insertVal = arr[i];
//被插入的位置(准备和前一个数比较)
int index = i-1;
//如果插入的数比被插入的数小
while(index>=0&&insertVal<arr[index]){
//将把arr[index] 向后移动
arr[index+1]=arr[index];
//让index向前移动
index--;
}
//把插入的数放入合适位置
arr[index+1]=insertVal;
}
}
}
(4)快速排序算法
快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。
一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。
public class Main{
public static void main(String[] args) {
int[] num= {9,6,5,4,7,6,2,1,10};
sort(num,0,num.length-1);
for(int n:num) {
System.out.print(n+" ");
}
}
//快速排序
public static void sort(int[] a,int low,int high){
int start = low;
int end = high;
int key = a[low];
while(end>start){
//从后往前比较
while(end>start&&a[end]>=key) {
//如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
end--;
}
if(a[end]<=key){
int temp = a[end];
a[end] = a[start];
a[start] = temp;
}
//从前往后比较
while(end>start&&a[start]<=key) {
//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
start++;
}
if(a[start]>=key){
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
//此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
//递归
if(start>low) {
sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
}
if(end<high) {
sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
}
}
}
}
(5)希尔排序算法
基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
public class Main{
public static void main(String[] args) {
int[] num= {9,6,5,4,7,6,2,1,10};
shellSort(num);
for(int n:num) {
System.out.print(n+" ");
}
}
public static void shellSort(int[] array) {
int gap = array.length;
while (true) {
gap /= 2; //增量每次减半
for (int i = 0; i < gap; i++) {
for (int j = i + gap; j < array.length; j += gap) {//这个循环里其实就是一个插入排序
int k = j - gap;
while (k >= 0 && array[k] > array[k+gap]) {
int temp = array[k];
array[k] = array[k+gap];
array[k + gap] = temp;
k -= gap;
}
}
}
if (gap == 1)
break;
}
}
}
(6)归并排序算法
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
public class Main{
public static void main(String[] args) {
int[] num= {9,6,5,4,7,6,2,1,10};
int[] nums=mergeSort(num,0,num.length-1);
for(int n:nums) {
System.out.print(n+" ");
}
}
//归并排序
public static int[] mergeSort(int[] nums, int l, int h) {
if (l == h)
return new int[] { nums[l] };
int mid = l + (h - l) / 2;
int[] leftArr = mergeSort(nums, l, mid); //左有序数组
int[] rightArr = mergeSort(nums, mid + 1, h); //右有序数组
int[] newNum = new int[leftArr.length + rightArr.length]; //新有序数组
int m = 0, i = 0, j = 0;
while (i < leftArr.length && j < rightArr.length) {
newNum[m++] = leftArr[i] <= rightArr[j] ? leftArr[i++] : rightArr[j++];
}
while (i < leftArr.length)
newNum[m++] = leftArr[i++];
while (j < rightArr.length)
newNum[m++] = rightArr[j++];
return newNum;
}
}
(7)桶排序算法
桶排序的基本思想是:把数组arr 划分为n个大小相同子区间(桶),每个子区间各自排序,最后合并。计数排序是桶排序的一种特殊情况,可以把计数排序当成每个桶里只有一个元素的情况。
1.找出待排序数组中的最大值max、最小值min
2.我们使用动态数组ArrayList 作为桶,桶里放的元素也用ArrayList 存储。桶的数量为(maxmin)/arr.length+1
3.遍历数组arr,计算每个元素arr[i] 放的桶
4.每个桶各自排序
import java.util.ArrayList;
import java.util.Collections;
public class Main{
public static void main(String[] args) {
int[] num= {9,6,5,4,7,6,2,1,10};
bucketSort(num);
}
//桶排序
public static void bucketSort(int[] arr){
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
//创建桶
int bucketNum = (max - min) / arr.length + 1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
for(int i = 0; i < bucketNum; i++){
bucketArr.add(new ArrayList<Integer>());
}
//将每个元素放入桶
for(int i = 0; i < arr.length; i++){
int num = (arr[i] - min) / (arr.length);
bucketArr.get(num).add(arr[i]);
}
//对每个桶进行排序
for(int i = 0; i < bucketArr.size(); i++){
Collections.sort(bucketArr.get(i));
}
int z=0;
int[] num=new int[arr.length];
for(int i=0;i<bucketArr.size();i++) {
for(int j=0;j<bucketArr.get(i).size();j++) {
while(z<num.length) {
num[z++]=bucketArr.get(i).get(j);
break;
}
}
}
for(int n:num) {
System.out.print(n+" ");
}
}
}
(8)基数排序算法
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
import java.util.ArrayList;
import java.util.List;
public class Main{
public static void main(String[] args) {
int[] num= {67,65,51,42,71,60,28,13,15};
sort(num);
for(int n:num) {
System.out.print(n+" ");
}
}
//基数排序
public static void sort(int[] array){
//首先确定排序的趟数;
int max=array[0];
for(int i=1;i<array.length;i++){
if(array[i]>max){
max=array[i];
}
}
int time=0;//判断位数;
while(max>0){
max/=10;
time++;
}//建立10个队列;
List<ArrayList> queue=new ArrayList<ArrayList>();
for(int i=0;i<10;i++){
ArrayList<Integer> queue1=new ArrayList<Integer>();
queue.add(queue1);
} //进行time次分配和收集;
for(int i=0;i<time;i++){ //分配数组元素;
for(int j=0;j<array.length;j++){ //得到数字的第time+1位数;
int x=array[j]%(int)Math.pow(10,i+1)/(int)Math.pow(10, i);
ArrayList<Integer> queue2=queue.get(x);
queue2.add(array[j]);
queue.set(x, queue2);
}
int count=0;//元素计数器; //收集队列元素;
for(int k=0;k<10;k++){
while(queue.get(k).size()>0){
ArrayList<Integer>queue3=queue.get(k);
array[count]=queue3.get(0);
queue3.remove(0);
count++;
}
}
}
}
}