1. 程式人生 > >資料結構與演算法之四 搜尋演算法

資料結構與演算法之四 搜尋演算法

視訊課堂https://edu.csdn.net/course/play/7621

目標

在本章中,你將學習: 使用線性搜尋技術搜尋資料和二叉搜尋技術搜尋資料 

線性搜尋: 是最簡單的搜尋方法, 也稱作順序搜尋, 包括將用該條目逐一與列表中的條目進行比較, 線性搜尋通過比較所需的元素與列表中第一個元素進行。


如果值不匹配:        則所需的元素將與列表中的第二個元素作比較。 如果值還是不匹配:      則所需的元素將與列表中的第三個元素作比較。
這個過程將一直持續下去,直到:     找到所需的元素或到達列表的未尾為止。 使用線性搜尋演算法編寫一個演算法以搜尋 員工記錄列表 中給定的員工的工號: 1.  讀取要搜尋的工號     ( 首先確定你要找的工號 ) 2. 設定 i = 0   n 是陣列的最大值下標 ( 上界 ) 3. 重複步驟 4 直到
i > n arr[i] = employee ID 4. i 值增加 1 5. 如果 i > n:            顯示 未找到      否則           
顯示 已找到

搜尋演算法的效率是由演算法的執行時間決定的。 在最佳情況下: 元素位於列表的第一個位置。 比較次數為 1 線性搜尋的最佳的效率是 O(1) 在最差情況下: 元素 位於列表中最後一個位置或者它根本不存在於該列表中 比較次數為元素的數。 線性搜尋最差的效率是 O(n)

在平均情況下: 線性搜尋的平均比較數由最佳和最差搜尋中的平均比較數決定 線性搜尋的平均效率是 1/2(n + 1)
課間思考

您要在一個包含 5000 個元素的陣列中應用線性搜尋來搜尋一個元素,如果在搜尋的 最後,您發現該元素不在該陣列中,則為了在該給定的列表中搜索所需的元素您要 進行多少次的比較?

答案: 5,000

問題描述: 編寫一個在含有最多 20 個數的陣列中使用線性搜尋演算法搜尋一個給定數的程式, 如果要搜尋的元素在列表中出現多次,則該程式應該顯示第一次出現的位置,還 應該顯示所作的比較總數。
二叉搜尋演算法: 用於搜尋大列表, 以十分少的比較來搜尋資料, 只要要搜尋的列表已經排序,則可以使用二叉搜尋演算法 考慮一個示例。 您要在以字母順序排列的電話目錄中搜索名字 Steve 要使用二叉搜尋演算法搜尋名字 Steve 在中間開啟電話目錄以確定哪一半包含該名字。 在那一半的中間再開啟以確定哪一半包含該名字。 重複此過程直到找到所需的名字為止。 二叉搜尋每次就減少了一半的搜尋頁數。

編寫一個演算法以實現二叉搜尋演算法。 1. 接受要搜尋的元素 ( 確定要查詢的值 ) 2. 設定 lowerbound = 0  3. 設定 upperbound = n – 1 4. 設定 mid = (lowerbound + upperbound)/2 5. 如果 arr[mid] = 所需元素: a. 顯示 已找到 b. 轉到步驟 10 6. 如果所需元素 < arr[mid]: a. 設定 upperbound = mid – 1

7. 如果所需元素 > arr[mid]: a. 設定 lowerbound = mid + 1 8. 如果 lowerbound <= upperbound: a. 轉至步驟 4 9. 顯示 未找到 10. 退出

在二叉搜尋演算法中的每個步驟中,搜尋區域都減半。 該演算法的最好情況是如果要搜尋的元素正好位於列表的最中間的位置: 此情況的比較數為 1 在最差情況下,列表中未找到所需元素 在第一次對分後,搜尋空間減少到 n/2 個元素,其中 n 是原始列表中的元素數。 第二次對分後,搜尋空間減少到 n/4 ,即 n/22 個元素。 經過第 i 次對分後,搜尋空間減少到 n/2i  元素。

課間思考

___________ 搜尋演算法中,您從列表的一端開始並且掃描整個列表直到找到所需 項或到達列表的末尾為止。


答案: 線性 要執行 __________ 搜尋演算法,列表應該是經排序的。 答案: 二叉
問題描述: 編寫一個程式,它使用二叉搜尋在含有最多 20 個元素的陣列中搜索一個數,假設 陣列元素是以升序輸入的。如果陣列中有多個要搜尋的數,則發現一個匹配後搜 索就停止了。程式還應該顯示所作的比較總數。

小結 在本章中,你已經學到: 線性搜尋的最佳效率是 O(1) ,最差效率 O(n) 要應用二叉搜尋演算法,應該確保要搜尋的列表是排過序的。 二叉搜尋的最佳效率是 O(1) ,最差效率是 O(log n)
/*從8個數中查詢數字*/
using System;

class Ban
{
	public static void Main(string[]args)
	{
		//int []arr={8001,8002,8003,8004,8007,8010,8005,8009}; //定義有8個整數的陣列		
		Console.WriteLine("請輸入您的工號個數:");
		int n; //n為陣列的上界
		n=Convert.ToInt32(Console.ReadLine());	//n就是陣列的長度(個數)
		
		int []arr=new int[n];		//定義有10個數字的陣列
		for(int j=0;j<n;j++)
		{
			Console.Write("請輸入第"+(j+1).ToString()+"個數:");
			arr[j]=Convert.ToInt32(Console.ReadLine());
		}		
		
		//3.重複步驟 4 直到 i > n 或 arr[i] = id 才退出.
	 char ch='y'; //定義我們不斷查詢的條件,如果為y|Y,則一直查詢;n|N:則退出查詢.
	 
	 while((ch=='y')||(ch=='Y'))
	 {
	 	Console.WriteLine("請輸入您要查詢的數字:");
	 	int id=Convert.ToInt32(Console.ReadLine());	//定義要查詢的資料元素	
		
		int lowerbound=0;
		int upperbound=n-1;
		int mid=(lowerbound+upperbound)/2;	//中間值下標
		
		//13	 
		while(lowerbound<=upperbound)	//實現找合適的中間值索引
		{
			if(id<arr[mid])
				upperbound=mid-1;
			else
				lowerbound=mid+1;
				
			mid=(lowerbound+upperbound)/2;	
			Console.WriteLine("low:"+lowerbound+"mid:"+mid+"upper:"+	upperbound);	
		}
		//針對找到資料元素,程式碼
				Console.WriteLine(arr[mid]);
		if(id==arr[mid])
				Console.WriteLine("ok");
		else		
			Console.WriteLine("沒有找到....");
			
		Console.WriteLine("您是否繼續查詢,是(y|Y),否(n|N):");
	  ch=Convert.ToChar(Console.ReadLine());	
	}//不斷查詢結束		
	}
}


/*使用二叉搜尋在含有最多20個元素的陣列中搜索一個數,假設陣列是以升序輸入的。如果陣列中有多個要搜尋的數,則發現一個匹配後搜尋就停止了。
程式還應該顯示所作的比較總數。
*/
using System;

class BinarySearch
{
	static void Main(string[]args)
	{
		int[]arr=new int[20];	//要搜尋的陣列
		int n;	//陣列中的元素數
		int i;	//獲取在陣列中儲存的元素數
		
		while(true)
		{
			Console.Write("請輸入陣列的元素個數:");
			string s=Console.ReadLine();
			n=Int32.Parse(s);
			if((n>0)&&(n<=20))
				break;
			else
				Console.WriteLine("\n陣列最少1個元素,最多20個元素.\n");	
		}
		//接受陣列元素
		Console.WriteLine("------------------------------------------");
		Console.WriteLine("---------------輸入陣列元素---------------");
		Console.WriteLine("------------------------------------------");
		
		for(i=0;i<n;i++)
		{
				Console.Write("<"+(i+1)+">");
				string s1=Console.ReadLine();
				arr[i]=Int32.Parse(s1);
		}
		char ch='y';
		do
		{
			//要搜尋的數
			Console.Write("請鍵入您要查詢的數");			
			int item=Convert.ToInt32(Console.ReadLine());
			//應用二叉搜尋
			int lowerbound=0;
			int upperbound=n-1;
			
			//獲取中間元素的索引
			int mid=(lowerbound+upperbound)/2;
			int ctr=1;
			
			while((item!=arr[mid])&&(lowerbound<=upperbound))	//在陣列中搜索元素的迴圈
			{
				if(item>arr[mid])
					lowerbound=mid+1;
				else
					upperbound=mid-1;
				mid=(lowerbound+upperbound)/2;
				//ctr++;
			}
	
			if(item==arr[mid])
				Console.Write("\n"+item.ToString()+"發現了位置:"+(mid+1).ToString());
			else
				Console.Write("\n"+item.ToString()+"在陣列中沒有發現");
				Console.Write("\n比較次數:"+ctr);
				Console.Write("\n繼續搜尋(y/n)");
				ch=char.Parse(Console.ReadLine());
		}while((ch=='y')||(ch=='Y'));
}	
}

/*
編寫一個在含有20個數的數中使用線性搜尋演算法一個給定數的程式,如果要搜尋的元素在列表中出現多次,則該程式應該顯示第一次出現的位置,還應該顯示所作
的比較總數。
*/
using System;

class SequentialSearch
{
	static void Main(string[]args)
	{
		int[]arr=new int[20];	//要搜尋的陣列
		int n;								//陣列中的元素
		int i;	//獲取在陣列中儲存的元素
		
		while(true)
		{
			Console.Write("請輸入陣列的元素個數:");
			string s=Console.ReadLine();
			n=Int32.Parse(s);
			if((n>0)&&(n<=20))
				break;
			else
				Console.WriteLine("\n陣列最少1個元素,最多20個元素.\n");	
		}
		//接受陣列元素
		Console.WriteLine("------------------------------------------");
		Console.WriteLine("---------------輸入陣列元素---------------");
		Console.WriteLine("------------------------------------------");
		
		for(i=0;i<n;i++)
		{
				Console.Write("<"+(i+1)+">");
				string s1=Console.ReadLine();
				arr[i]=Int32.Parse(s1);
		}
		char ch='y';
		int  ctr;
		
		do
		{
			//接受要搜尋的數
			Console.Write("\n請輸入您要搜尋的數:");
			int item=Convert.ToInt32(Console.ReadLine());
			//應用線性搜尋
			ctr=0;
			for(i=0;i<n;i++)
			{
				ctr++;
				if(arr[i]==item)
				{
					Console.WriteLine("\n"+item.ToString()+"發現在位置"+(i+1).ToString());
					break;	
				}	
			}
			if(i==n)
			{
				Console.WriteLine("\n"+item.ToString()+"在陣列中沒有發現元素");
				Console.WriteLine("\n比較的次數為:"+ctr);
				Console.Write("\n繼續搜尋(y/n):");
				ch=Char.Parse(Console.ReadLine());	
			}
		}while((ch=='Y')||(ch=='y'));
	}	
}