線性表的查找——二分查找(折半查找)

一,可以使用二分查找的要求

  • 線性表必須採用順序存儲結構
  • 表中元素按關鍵字有序排列

二,查找的過程

  1. 從表的中間記錄開始,如果查找值與中間記錄的關鍵字相等,則查找成功;
  2. 如果查找值大於或小於中間記錄的關鍵字,則在表中大於或小於中間記錄的那一半中查找;
  3. 重複上面步驟,直到查找成功,或者表中無查找值,則返回錯誤。

三,算法步驟

  •  定義新的low, high。並將low賦值爲0,high賦值爲表長

  • 當low小於high時,循環執行下面操作

  1. mid取low和high的中間值,此時有三種方法:mid = (low+high)/2     mid=low+(high-low)/2     mid=low+((high-low)>>1)
  2. 將查找值n與中間位置關鍵字進行比較,相等則查找成功,跳出循環
  3. 不相等則利用中間位置,將表分爲兩部分。如果小於則high=mid-1;否則low=mid+1;

 


  • 一直到循環結束,如果還未找到查找值,則顯示錯誤

四,一種代碼實現方法

#include<iostream>
using namespace std;

int main()
{
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int low = 0, high = 9;
	cout << "想要找的值:";
	int n;
	cin >> n;

	//採用循環方法
	while (low <= high)
	{
		int mid = (low + high) / 2;     //取中值
		if (a[mid] == n)     //找到
		{
			cout << mid;
			break;
		}
		else if (a[mid] < n)      //小於所求值
		{
			low = mid + 1;
		}
		else                       //大於所求值
		{
			high = mid - 1;
		}
	}
	if (low>high)                  //線性表中無所求值,顯示錯誤
	{
		cout << "error";
	}
	system("pause");
	return 0;
}

另一種實現方法

#include<iostream>
using namespace std;

void Find(int *a, int low, int high, int n)
{
	if (low > high)         //發生錯誤
	{
		cout << "error";
	}
	else
	{
		int mid = (low + high) / 2;    //求中間值
		if (a[mid] == n)      //找到所求值
		{
			cout << mid;
		}
		else if (a[mid] < n)               //兩種函數循環方法
		{
			Find(a, mid + 1, high, n);
		}
		else
		{
			Find(a, low, mid - 1, n);
		}
	}
}

int main()
{
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int low = 0, high = 9;
	cout << "想要找的值:";
	int n;
	cin >> n;
	Find(a, low, high, n);      //將數據傳入函數中
	system("pause");
	return 0;
}

拓展

一,求第一個等於查找值的位置

此時判斷的重點就在於,當mid記錄的關鍵字與所求值相同時,還需要判斷mid前的值是否與所求值相同;

如果相同則說明當前mid還不是第一個等於所求值的,所以仍需將high賦值爲mid-1,繼續循環。

代碼

#include<iostream>
using namespace std;

int main()
{
	int a[10] = { 1, 2, 3, 5, 5, 5, 5, 8, 9, 10 };
	int low = 0, high = 9;
	cout << "想要找的值:";
	int n;
	cin >> n;

	//採用循環方法
	while (low <= high)
	{
		int mid = (low + high) / 2;     //取中值
		if (a[mid] < n)     //小於情況
		{
			low = mid + 1;
		}
		else if (a[mid] > n)      //大於情況
		{
			high = mid - 1;
		}
		else                       //等於
		{
			if (a[mid - 1] != n || mid == 0)      //等於且當前mid即爲第一個值
			{
				cout << mid;
				break;
			}
			high = mid - 1;            //否則繼續循環
		}
	}
	if (low>high)                  //線性表中無所求值,顯示錯誤
	{
		cout << "error";
	}
	system("pause");
	return 0;
}

二,查找最後一個小於所求值的位置

即爲上面的第一個等於查找值位置的前一個

代碼

#include<iostream>
using namespace std;

int main()
{
	int a[10] = { 1, 2, 3, 5, 5, 5, 5, 8, 9, 10 };
	int low = 0, high = 9;
	cout << "想要找的值:";
	int n;
	cin >> n;
	int mid;
	//採用循環方法
	while (low <= high)
	{
		mid = (low + high) / 2;     //取中值
		if (mid == 0)
		{
			break;
		}
		//cout << mid<<endl;
		if (a[mid] < n)     //小於情況
		{
			low = mid + 1;
		}
		else if (a[mid] > n)      //大於情況
		{
			high = mid - 1;
		}
		else                       //等於
		{
			if (a[mid - 1] != n)      //等於且當前mid即爲第一個等於所求值的值
			{
				cout << mid - 1;      //則返回第一個值的前一個
				break;
			}
			high = mid - 1;            //否則繼續循環
		}
	}
	if (low>high || mid ==0)                  //線性表中無所求值,顯示錯誤
	{
		cout << "error";
	}
	system("pause");
	return 0;
}

 

 

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章