C#實(shí)現(xiàn)折半查找算法
折半查找,也叫二分查找,當(dāng)在一個(gè)數(shù)組或集合中查找某個(gè)元素時(shí),先定位出中間位置元素,如果要查找的元素正好和該中間位置元素相等,通過一次查找,就能找到匹配元素;如果要查找的元素小于該中間位置元素,就拋棄后面一半的元素,在前面一半的元素中再定位出中間位置元素,如此反復(fù),直到找到匹配元素;如果要查找的元素大于該中間位置元素,就拋棄前面一半的元素,在后面一半的元素中定位出中間位置元素,如此反復(fù)。
面臨的第一個(gè)問題是:中間位置元素如何定位?在折半查找中規(guī)定:當(dāng)元素個(gè)數(shù)是奇數(shù),比如有3個(gè)元素,中間位置元素是索引為1的元素;當(dāng)元素個(gè)數(shù)是偶數(shù),比如有4個(gè)元素,索引為1和2的元素理論都是中間位置元素,但在折半查找中,把后面這個(gè),即索引為2的元素視為中間位置元素。
面臨的第二個(gè)問題是:由于,要查找的元素和中間位置元素之間需要比較,我們在比較之前,勢必要讓數(shù)組按升序或降序來排列。
自定義一個(gè)類,該類維護(hù)著一個(gè)int[]類型數(shù)組,通過構(gòu)造函數(shù)確定數(shù)組長度和對數(shù)組進(jìn)行排序,并提供打印數(shù)組元素的方法,以及折半算法。
public class MyArray { private int[] arr;//內(nèi)部維護(hù)著一個(gè)數(shù)組 private static Random r = new Random();//用它來生成數(shù)組的隨機(jī)元素 //通過構(gòu)造函數(shù)來確定內(nèi)部數(shù)組的長度,并生成數(shù)組的隨機(jī)元素,并對數(shù)組元素排序 public MyArray(int size) { arr = new int[size]; for (int i = 0; i < size; i++) { arr[i] = r.Next(1, 100); } Array.Sort(arr); } //折半查找算法 返回查找元素的索引位置 public int HalfSearch(int key) { int low = 0;//低點(diǎn),初始值設(shè)置成最低點(diǎn),即索引0 int high = arr.Length - 1;//高點(diǎn),初始值設(shè)置成最高點(diǎn),即索引數(shù)組最后一個(gè)位置 //如果數(shù)組元素個(gè)數(shù)是偶數(shù),比如4個(gè),索引2和3都是中間位置,用以下算法中間位置指向索引3 //如果數(shù)組元素個(gè)數(shù)是奇數(shù),比如3個(gè),索引1是中間位置,用以下算法中間位置指向索引1 int middle = (low + high + 1)/2; int location = -1;//找不到就返回-1 //循環(huán),找不到就一直查找 do { //每次循環(huán),把低點(diǎn)和高點(diǎn)位置的元素打印出來 Console.WriteLine(PrintSectionElements(low, high)); Console.WriteLine(); //如果要查找元素是中間位置的元素,就返回中間位置這個(gè)索引 if (key == arr[middle]) { location = middle; } else if (key < arr[middle]) //如果要查找元素小于中間位置元素,把中間位置前面的索引設(shè)為高點(diǎn) { high = middle - 1; } else//如果要查找元素大于中間位置元素,把中間位置后面的索引設(shè)為低點(diǎn) { low = middle + 1; } //如果代碼運(yùn)行到此處,說明還沒有找到匹配元素,由于以上重新設(shè)置了低點(diǎn)或高點(diǎn),所以這里也要重新設(shè)置中間位置 middle = (low + high + 1)/2; } while ((low <= high) && (location == -1)); return location; } //打印2個(gè)位置間的數(shù)組元素 public string PrintSectionElements(int low, int high) { string temp = ""; //對于2個(gè)位置間的元素打印出元素并跟上一個(gè)空格位置 for (int i = low; i <= high; i++) { temp += arr[i] + " "; } return temp; } //重寫ToString方法,把數(shù)組所有的元素都打印出來 public override string ToString() { return PrintSectionElements(0, arr.Length - 1); } }
以上,折半查找的目的是找到匹配元素在數(shù)組中的索引位置,為此,通過需查找元素和中間位置元素大小的比較,不斷地調(diào)整低點(diǎn)、高點(diǎn)和中間位置。另外,在C#中,1/2的結(jié)果是0。
客戶端。
class Program { private static int key; //需查找元素 private static int position;//匹配元素所在的位置 static void Main(string[] args) { MyArray myArray = new MyArray(7); //把所有元素打印出來 Console.WriteLine(myArray); Console.WriteLine("請輸入需要查找的元素或輸入-1退出 "); key = Convert.ToInt32(Console.ReadLine()); Console.WriteLine(); while (key != -1) { //調(diào)用折半算法得出所需查找元素的位置 position = myArray.HalfSearch(key); if (position == -1) //說明沒有找到需要匹配的元素 { Console.WriteLine("沒有找到元素{0}", key); } else { Console.WriteLine("在{0}號位置查到元素{1}", position, key); } Console.WriteLine("請輸入需要查找的元素或輸入-1退出 "); key = Convert.ToInt32(Console.ReadLine()); Console.WriteLine(); } } }
用時(shí)間復(fù)雜度來描述折半查找的效率
假設(shè)一個(gè)數(shù)組有1023個(gè)元素,由于可以表示成"1023=2?-1"等式,所有n=10。對該數(shù)組每進(jìn)行一次折半,相當(dāng)于除以2,也就是說,在該數(shù)組中查找某個(gè)元素,最多需要10次,就可以查到匹配元素。
對于"2?-1"這個(gè)表達(dá)式,當(dāng)n=30,就表示10億,使用折半查找,10億個(gè)元素最多需要30次就能找到匹配元素。而使用線性查找需要平均5億次的查找。2種算法的效率由此可見一斑。
把折半查找、二分查找的時(shí)間復(fù)雜度寫成O(log n),稱為"對數(shù)運(yùn)行時(shí)間",讀為"對數(shù)階"。
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
C#驗(yàn)證用戶輸入信息是否包含危險(xiǎn)字符串的方法
這篇文章主要介紹了C#驗(yàn)證用戶輸入信息是否包含危險(xiǎn)字符串的方法,可針對and、or、exec、insert、select等SQL操作技巧進(jìn)行過濾操作,非常具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03C#怎么實(shí)現(xiàn)手機(jī)短信發(fā)送功能
為了個(gè)人信息的安全,很多網(wǎng)站都有短信發(fā)送的功能,究竟是怎么實(shí)現(xiàn)的呢?對于個(gè)人站長來說的話,通過使用sms短信通知api接口相對比較簡單,下面小編給大家介紹具體實(shí)現(xiàn)過程,對c#怎么實(shí)現(xiàn)手機(jī)短信發(fā)送功能感興趣的朋友一起學(xué)習(xí)吧2015-12-12Unity3D實(shí)現(xiàn)NavMesh導(dǎo)航網(wǎng)格尋路
這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)NavMesh導(dǎo)航網(wǎng)格尋路,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05C#使用FileStream循環(huán)讀取大文件數(shù)據(jù)的方法示例
這篇文章主要介紹了C#使用FileStream循環(huán)讀取大文件數(shù)據(jù)的方法,結(jié)合實(shí)例形式分析了FileStream文件流的形式循環(huán)讀取大文件的相關(guān)操作技巧,需要的朋友可以參考下2017-05-05C# ComboBox控件“設(shè)置 DataSource 屬性后無法修改項(xiàng)集合”的完美解決方法
這篇文章主要介紹了C# ComboBox控件“設(shè)置 DataSource 屬性后無法修改項(xiàng)集合”的解決方法,非常不錯(cuò)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11