1. 程式人生 > >C程式設計--查詢(二分法查詢/折半查詢)

C程式設計--查詢(二分法查詢/折半查詢)

二分法查詢/折半查詢

說明:折半搜尋(half-interval search),也稱二分搜尋(binary search)、對數搜尋(logarithmic search),是一種在有序陣列中查詢某一特定元素的搜尋演算法。

搜尋過程從陣列的中間元素開始,如果中間元素正好是要查詢的元素,則搜尋過程結束;如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中查詢,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為空,則代表找不到。這種搜尋演算法每一次比較都使搜尋範圍縮小一半

  • 優缺點
  1. 優點:是比較次數少,查詢速度快,平均效能好;
  2. 缺點:是要求待查表為有序表,且插入刪除困難。
    因此,折半查詢方法適用於不經常變動而查詢頻繁的有序列表。
  • 演算法步驟描述
    ① 首先確定整個查詢區間的中間位置 mid = ( left + right )/2 。
    ② 用待查關鍵字值與中間位置的關鍵字值進行比較; 
    若相等,則查詢成功 
    若大於,則在後(右)半個區域繼續進行折半查詢 
    若小於,則在前(左)半個區域繼續進行折半查詢。
    ③ 對確定的縮小區域再按折半公式,重複上述步驟。最後,得到結果:要麼查詢成功, 要麼查詢失敗。折半查詢的儲存結構採用一維陣列存放。
  • 程式碼實現
  1. 主函式:
int main()
{	
	int array[] = {1,2,3,4,5,6,7,8,9};
	int length = sizeof(array)/sizeof(array[0]);//用sizeof()獲取陣列的長度
	int element;
	scanf("%d",&element);

	int location = binary_research(array,length,element);

	if(location>=0)
		printf("The element's location is %d\n",location);
	else
		printf("Don't exit this element.\n");
	return 0;
} 
  1. 折半查詢函式部分:
//在有序表R[0..n-1]中進行二分查詢,成功時返回結點的位置,失敗時返回-1
int binary_research(int arr[],int length,int element)
{
	int left=0,right=length-1; //置當前查詢區間上、下界的初值

	while(left<=right)
	{	
		int mid = (left+right)/2;//會有整數溢位的問題,具體見函式說明

		if(arr[mid]>element)
			right = mid - 1; //繼續在R[left..mid-1]中查詢
		else if(arr[mid]<element)
			left = mid + 1;	 //繼續在R[mid+1..right]中查詢
		else 
			return mid;		 //查詢成功返回
	}
	return -1;	//當 left>right 時表示所查詢區間內沒有結果,查詢失敗
}
關於上述函式說明:
  1. 在第8行程式碼中:int mid = (left+right)/2;
    使用(left+right)/2會有整數溢位的問題。
    問題會出現在當left+right的結果大於表示式結果型別所能表示的最大值時, 這樣,產生溢位後再/2是不會產生正確結果的。
    優化方法:int mid = left + (left - right)/2; //防止越界

因此改進後的程式為:

int binary_research(int array[],int length,int target)
{
    int low=0,high=length-1;
	while(low<=high)
        {
            int mid=low+(high-low)/2;//優化溢位問題
            if(array[mid]>target)
                high=mid-1;
            else if(array[mid]<target)
            low=mid+1;
            else
                return mid;
        }
    return-1;
}

另外一種寫法:int binary_research(int arr[],int low,int high,int target);

#include<stdio.h>

int binary_research(int arr[],int low,int high,int target);

int main()
{	
	int array[] = {1,2,3,4,5,6,7,8,9};//陣列中的數(由小到大)
	int length = sizeof(array)/sizeof(array[0]);//用sizeof()獲取陣列的長度
	int low=0,high=length-1;
	int element;
	scanf("%d",&element);

	int location = binary_research(array,low,high,element);

	if(location>=0)
		printf("The element's location is %d\n",location);
	else
		printf("Don't exit this element.\n");
	return 0;
} 

int binary_research(int array[],int low,int high,int target)
{
	while(low<=high)
        {
            int mid=low+(high-low)/2;//優化溢位問題
            if(array[mid]>target)
                high=mid-1;
            else if(array[mid]<target)
            low=mid+1;
            else
                return mid;
        }
    return-1;
}

除此以外還可以使用 遞迴函式 實現折半查詢:

//遞迴函式實現
int binary_research(int array[],int low,int high,int target)
{
    int mid=low+(high-low)/2;//優化溢位問題
	if(low>high)//查詢完畢沒有找到答案,返回-1
        return -1;
    else
    {
        if(array[mid]==target)
            return mid;//找到!返回位置.
        else if(array[mid]>target)
            return binary_research(array,low,mid-1,target);//找左邊
         else
            return binary_research(array,mid+1,high,target);//找右邊
    }
}

參考文章:
1.https://blog.csdn.net/qq_31828515/article/details/51791833
2.https://baike.baidu.com/item/二分查詢/10628618?fr=aladdin