折半查找:
說明:插入和進制轉換用到了 數組的操作,就當對數組進一步瞭解了。
要求:一定是對有序序列的查找
/*
需求:將一個已知元素插入到一個有序數組中,要求不改變數組順序,打印元素應該插入數組位置的角標。
思路:1、可以利用折半查找的方式,先定義兩個變量,一個初始化0角標,作爲最小值,一個初始化爲最後一個角標,作爲最大值,
再定義一個變量,存儲最小值與最大值的一半,也就是中間位置,然後將已知元素與中間值位元素進行比較。
2、如果比中間值元素大,則將最小值變爲中間值加1,繼續取最小值與最大值的中間值元素與已經元素進行比較,以此反覆
3、如果比中間值元素小,則將最大值變爲中間值減1,繼續取最小值與最大值的中間值元素與已經元素進行比較,以此反覆
*/
public class BinarySearch1
{
/***************************
折半查找 Version-1.0
這個折半查找我在寫的時候有一點問題,
問題一:if(min>max)這句話的判斷不能直接放在開頭,因爲如果查詢的數小於頭會報數組越界錯誤
原因:此時max已經指向-1,所以mid取-1,所以越界了
***************************/
public static int binarySearch1(int key,int arr[])
{
int min = 0;
int max = arr.length-1;
int mid = (min+max)/2;
while(key!=arr[mid])
{
//位置1:
//if(min>max)
//{
// return -1;
//}
mid = (min+max)/2;
if(key>arr[mid])
{
min = mid + 1;
}else if(key<arr[mid])
{
max = mid - 1;
}
if(min>max)
{
return -1;
}
mid = (min+max)/2;
}
return mid;
}
/*
折半查找 version-2.0
這種方法不會出現問題一,因爲一旦min>max了,就跳出循環了,不會出現越界問題了
*/
public static int binarySearch2(int key,int arr[])
{
int min = 0;
int max = arr.length-1,mid;
while(min<=max)
{
mid = (min+max)>>>1;
if(key>arr[mid])
{
min = mid + 1;
}else if(key<arr[mid])
{
max = mid - 1;
}else
{
return mid;
}
}
return -1;
}
public static void main(String []args)
{
int arr1[] = {0,3,7,9,11,12,14,70,80,90,100};
int key = 3;//11,100
int y = binarySearch1(key,arr1);
int z = binarySearch2(key,arr1);
System.out.println("使用版本1.0,查詢到的腳標數的腳標是:"+y);
System.out.print("使用版本2.0,查詢到的腳標數的腳標是:"+z);
}
}
結果是:
折半查找的插入點返回
如果查找的數字是不存在的,我想知道他可以插在那個地方:
先要知道一個概念,如果沒有查到想要的數,那麼min和max指向哪裏?
畫圖理解二分法插入:
那麼根據上面的查找,只需將return -1改爲return min;就可以了!
public class BinarySearch1
{
//二分查找法改進爲可以找不存在的數的插入點
public static int binarySearch2(int key,int arr[])
{
int min = 0;
int max = arr.length-1,mid;
while(min<=max)
{
mid = (min+max)>>>1;
if(key>arr[mid])
{
min = mid + 1;
}else if(key<arr[mid])
{
max = mid - 1;
}else
{
return mid;
}
}
//修改這裏的返回值
return min;
}
public static void main(String []args)
{
int arr1[] = {0,3,7,9,11,12,14,70,80,90,100};
int key = 5;
int z = binarySearch2(key,arr1);
System.out.println("使用版本2.0,查詢數:"+key+" 的腳標是:"+z);
int a = Arrays.binarySearch(arr1, key);
System.out.println("使用Arrays下的方法,查找 "+key+" 的腳標是:"+a);
}
}
運行:
這裏根據java.util.Arrays類的方法binarySearch進行比較,感覺人家寫得好啊,我這個找出來的不知道是查到了還是插入點,人家的方法清楚,正數是查到的腳標,負數時將插入的腳標。
優化:將return min;可以改寫爲return -1-min。結果就和他的一樣了。
進制轉換
十進制轉十六進制:
/*
使用查表法將十進制轉換爲十六進制
*/
public class ToHex1
{
public static char[] toHex(int num)
{
if(num==0)
{
char []c1 = {'0'};
return c1;
}
//定義一個包含二進制、八進制、十六進制的表
char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//定義一個臨時容器
char c[] = {'0','0','0','0','0','0','0','0'};
//定義一個操作數組的指針
int i = c.length;
//利用與低位最大值的方式取出低位,存到臨時數組中
while(num!=0)
{
c[--i] = hex[num&15];//--pos倒着往臨時容器裏存
num = num>>>4;//無條件右移相應位數
}
return c;
}
public static void main(String args[])
{
int a = 60;
System.out.print(toHex(a));
}
}
結果:
十進制轉二進制,八進制,十六進制
將以上方法封裝升級,轉換成可以重複利用,並可以實現十進制轉二進制和八進制:
public class ToHex1
{
//抽象出來的方法,base是“與(&)”的對象,move是移動的位數
public static void convert(int num ,int base,int move)
{
//0比較特殊,需要特殊對待
if(num==0)
{
char []c1 = {'0'};
System.out.print("0");
return;
}
char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char c[] = new char[32];
int i = c.length;
while(num!=0)
{
c[--i] = hex[num&base];
num = num>>>move;
}
for(int j=i;j<c.length;j++)
{
System.out.print(c[j]);
}
}
//轉二進制
public static void toBinary(int num)
{
convert(num,1,1);
//換行
System.out.println();
}
//轉八進制
public static void toOctal(int num)
{
convert(num,7,3);
//換行
System.out.println();
}
//轉十六進制
public static void toHex(int num)
{
convert(num,15,4);
//換行
System.out.println();
}
public static void main(String args[])
{
int a = 60;
System.out.print("數"+a+"對應二進制:");
toBinary(a);
System.out.print("數"+a+"對應八進制:");
toOctal(a);
System.out.print("數"+a+"對應十六進制:");
toHex(a);
}
}
運行結果(0和60):
總結:
1.折半查找的思想
2.對摺半查找的min和max的理解可以推導出:對不存在數的插入位置的推斷。
3.進制轉換,“與(&)”的運用,取位操作。