日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

顺序表查找+折半查找(二级)

發(fā)布時間:2024/4/13 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 顺序表查找+折半查找(二级) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們講了各種數(shù)據(jù) 結(jié)構(gòu)之后,比如講了線性表了,講了棧和隊列,講了樹和二叉樹,講了圖之后呢,我們最后還有兩個專題,一個叫查找,一個叫排序,我們先看看查找,查找包括哪些內(nèi)容啊,第一個線性表的查找,數(shù)組或者鏈表的查找,這是一個,還有一個呢,樹的查找,涉及到的一個概念二叉查找樹,還有一個是哈希表的查找,哈下表的查找開始我們講集合的時候其實已經(jīng)接觸過了,最后我們再講一下Java里面有哪些查找樹和哈希表,這就是我們查找樹的內(nèi)容,線性表的查找我們以數(shù)組為例來進行講解,線性查找有順序查找和折半查找,跟底層采用什么存儲結(jié)構(gòu)是沒有關(guān)系的,只不過我們目前是采用數(shù)組來實現(xiàn),大家也可以采用相關(guān)的鏈表,現(xiàn)在我們先來看這一部分1. 順序查找:比如我們這里面定義了一個數(shù)組,這個數(shù)組里面存了分數(shù),我要在這里面找一個分數(shù),找100分,在成績中查找分數(shù)是100的第一個分數(shù),怎么辦,有沒有順序,他是不是大小排列的,不是大小排列的,他不是大小排列的,所以這個時候你只能干什么,只能逐個來比較,最終找到第一個100的,這個效率是高還是低,這個效率是低的,但是你沒有辦法,你只能這么來,要是學生呢,就復(fù)雜了唄,數(shù)組里面放的就不是int了,成了Student了,那也類似嗎,但是還有一種情況,提高效率的話,這個數(shù)組里面放的不能是分數(shù)了,他現(xiàn)在是不是有序的,有序的我們就能改變一種思路,你沒有必要一個一個找了,可以折半查找,我要找8份,你怎么找8分,我先找最中間的那個,這個6居然比8小,只要這一半,可以再折半,每次砍掉長度的?,這個效率是非常高的,但是他有前提條件,有什么條件,它是有序的,還有一點呢,那對這個折半查找,他要求采用數(shù)組,要是你不采用數(shù)組的話,他底層鏈表也是不連續(xù)的,這樣一來效率也不怎么高,這是我們所說的我們再來看看折半查找,折半查找也叫二分查找,使用這種查找的話需要滿足兩個條件1. 第一個要求是順序存儲結(jié)構(gòu)2. 第二個必須是有序的,比如這個數(shù)組從5一直到52,是不是一直都是有序的,這種情況下我們要是再按照順序查找的話我們就會發(fā)現(xiàn)他的缺點,效率比較低,那么我們怎么來辦,折半查找,我們來看一下,我們要在這里找21,該怎么找,就是這么來找,我們上面寫的0到10是什么意思,是索引,在往下邊是分數(shù),是兩個指針,也就是兩個整形的變量,low首先指向第一個,是0吧,high指向最后,是10,(0+10)/2=5,整除就可以了,5,mid是什么意思,中間,索引就是5,你找的是誰,我們找的就是21,拿著21跟56比,這一半就全部排出了,肯定不在有一半了,一共有一億個樹,一下子就消滅了5000萬,5000萬不用考慮了,哪還有5000萬呢,在分一次就是2500萬,是不是又沒有了,我們講過2倍2倍的增,現(xiàn)在我們是?的減,這個速度是非??斓?那告訴我下一步該怎么辦了,這個Low變不變,;low還是0,low是不變的,mid是計算出來的,下次改的是high,起點還是low,終點是high,它的索引是4,怎么成了4了,之前那個冪的是5,5前面這個一個唄,找他就可以了,high=mid-1=4,一個是0,一個是4,頭0尾4,取中間值,(0+4)/2=2,mid等于2,拿著這個21和19比,這個肯定不會的,就排除了那下一步告訴我指針該怎么變,low和high該怎么變,high要不要變,high不變,范圍又是這一塊了,high不變還是4,low應(yīng)該是幾,是mid+1,是不是3,(3+4)/2你可別來個3.5,沒有3.5,3,mid指向3,指向3了,找到了,他這個時間復(fù)雜度是多少啊就是我們之前說的log2 n,每次他都會減少二分之一,這個log2 n是什么含義,這個n和log2 n有什么差別,如果n是10億次,如果你的級別是n,你就得找10億次,但是如果你是log2 n,n給他10億的話,就是2的30次方就是10億,30次就夠了,20次和10億次天差地別,這你知道這個效率有多高,明確一下,這個效率是特別高的,這是我們講的一個內(nèi)容,我們舉了這個例子好在什么程度,我們的high動了一次,high要變成mid-1,下次再比的話low又要變一下,low要變成mid+1,這里面就是我們要寫的一個算法,你告訴我他什么時候可以結(jié)束啊,什么時候開始結(jié)束,這個值等于21的時候就結(jié)束了,是那樣嗎那你給我找個85,找個85的,這里面沒有85,一個80,一個88,那怎么辦,那就是按照剛才的規(guī)則一直在動,動來動去,就會出現(xiàn)一個情況,什么情況,這個圖已經(jīng)很明白了,low,high,取中間,low等于9,mid等于9,到這兒還沒有結(jié)束呢,結(jié)果拿著88和85相比,他是不是在這一邊呢,結(jié)果變成low等于9,mid現(xiàn)在也是9,他在這邊的就是high了,high等于mid-1他的前一個,high變成8了,你看怎么了,low比high還大,說明沒有找不到,所以找到?jīng)]找到,內(nèi)容都在這兒,這是我們講的遞歸,明確折半查找的思路,第二個知道他的時間復(fù)雜度,log2 n級別的,這個效率特別高,下邊我們就來寫這個代碼了 package com.learn.search;/*** 查找功能:在分數(shù)中查詢指定分數(shù)的索引,在第幾個位置* * 關(guān)于這個順序的查找非常的簡單,* 那我們分析一下這個時間復(fù)雜度是多少,* 他的時間復(fù)雜度寫一個大歐,* T(n) = O(n)* 如果這個數(shù)組的長度是n個的話,* 那平均下來會找一半,去掉系數(shù)是O(n)* 所以這個數(shù)如果幾百萬的話,查找次數(shù)還是挺多的* 效率還是挺低的* 再寫一個S(n),空間復(fù)雜度是多少* 不需要用到什么變量,只要一個index,一個i* 別的他不需要,所以這個不需要占用更多的空間* S(n) = O(1)* 效率低下* 這個講數(shù)組操作的時候都應(yīng)該已經(jīng)講過* 非常簡單* 逐個比較,如果找到,返回數(shù)據(jù)或者索引* 找不到就返回null或者-1* 可以是順序表,也可以是鏈表* 在各個節(jié)點查找概率相同的情況下,* 默認的查詢長度是一半,* 所以時間復(fù)雜度是O(n)* 這個非常的簡單* @author Leon.Sun**/ public class TestSearch1 {public static void main(String[] args) {/*** 第一步給定分數(shù)數(shù)組* * 給定數(shù)組*/int [] scoreArr = {89,45,78,45,100,98,86,100,65};/*** 給定要查找的分數(shù)* * 分數(shù)就是他了* * 找個65*/// int score = 100;/*** 一共9個數(shù),索引是8*/// int score = 65;/*** 找個650,是-1*/int score = 65;/*** 完成查找* * 最終我們會得到一個index* * 默認的index是-1*/ // int index = -1;/*** 最難的這一步怎么辦* 能怎么辦,來一個for循環(huán)* * 但是對于查找我們要提取一個方法*/ // for(int i=0;i<scoreArr.length;i++) { // /** // * 逐個判斷 // */ // if(scoreArr[i]==score) { // /** // * 那怎么辦,找到了沒有 // * 能return 嗎,return那main方法就結(jié)束了 // * 這不能用return,index就等于i // * 找到就是i // */ // index = i; // /** // * 再加個操作 // * 找到100后面就不比了, // * // * break一下也就不循環(huán)了 // */ // break; // } // }/*** 輸出結(jié)果* * 輸出一下,怎么輸出啊* 那就看index等于幾了唄* 如果index等于-1,那就輸出一下不存在* * 一共是分4步,我們都一斤完成3步了* */ // if(index==-1) { // System.out.println("該分數(shù)不存在"); // }else { // /** // * 100的索引是4,是4嗎 // * // */ // System.out.println(score + "索引是:" + index); // }/*** 怎么查找,剛才我們要查找的話,你不僅知道你要干什么* 你還要知道怎么來完成,你們知道這個思路嗎,* 現(xiàn)在不用了,你只要知道你想干什么就行了* 我想查找,直接調(diào)用一個search,* 這個他里面是怎么實現(xiàn)的,我才不管呢* * 這邊傳誰,傳一個scoreArr,再傳一個score* 有沒有問題,沒有了,*/int index = search(scoreArr,score);}/*** 返回值是什么,是int,索引嗎* 需要傳一個什么內(nèi)容,* * 這里面我們應(yīng)該傳一個數(shù)組,還要穿一個score* * 方法提取,這個方法就可以重用* * 我們這里改一下不叫scoreArr,難道只能改分數(shù)嗎* 不僅可以找分數(shù),還可以找其他的*/public static int search(int[] arr,int key) {int index = -1;for(int i=0;i<arr.length;i++) {if(arr[i]==key) {index = i;break;}}if(index==-1) {System.out.println("該分數(shù)不存在");}else {System.out.println(key + "索引是:" + index);}/*** 返回這個索引就行了*/return index;}} package com.learn.search;/*** 告訴我他又什么前提,* 前提是什么,第一個順序結(jié)構(gòu),第二個按照關(guān)鍵字有序排列* 滿足這兩個條件* @author Leon.Sun**/ public class TestSearch2 {public static void main(String[] args) {/*** 第一步干什么啊,給定數(shù)組*/int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };/*** 第二步給定要查找的值* 你要找誰,找key*/// int key = 2;/*** 10的索引是幾*/int key = 10;/*** 再找一個6*/ // int key = 6;/*** 進行查找* 這個查找叫折半查找或者叫二分查找*/ // int index = -1;int index = binarySearch(array,key);/*** 輸出結(jié)果* * 最終要返回他的索引*/if(index==-1) {System.out.println("不存在");}else {System.out.println(key + "的索引是" + index);}}/*** 你知道我們這里面該怎么辦* 兩種方案:* 第一個方案:不使用遞歸* @param array* @param key* @return*/public static int binarySearch(int[] array,int key) {/*** 首先指定low和high*/int low = 0;int high = array.length - 1;/*** 折半查找* * while一直查找* 如果low一直小于high就可以一直進行* 如果Low小于high就一直循環(huán)著,* 循環(huán)怎么辦,* * 你看他什么時候循環(huán)就結(jié)束了,* 第一個return了就結(jié)束了* 找到了就結(jié)束了,還有一個循環(huán)完了就結(jié)束了* low大于high了及* 這里改成小于等于,* 所以有些細節(jié)方面,* 總體思路明白當是我們寫代碼的時候要注意細節(jié),* 不使用遞歸的我們先想到這兒,* 這和遞歸有關(guān)系嗎,* 折半查找還有遞歸* 差不多吧,我覺得和遞歸有關(guān)系* 有什么關(guān)系,* 首先這個數(shù)組我要進行折半查找,* 起始點是0,終止點是10,* 下一次我要在這個數(shù)組里面再次進行折半查找* 我們把這部分看成是一個數(shù)組唄,* 起始是0,這是4嗎,* 下一次我要在這兩個里面進行折半查找嗎* 這是3這是4,* 遞歸查找,我們可以把數(shù)組的范圍縮小* 指定他的起始和終止位置* 一直在進行折半查找* 我們的操作一直在重復(fù)* 從這個角度來說我們再來寫一個折半查找的程序*/while(low<=high) {/*** 下一步要求得mid* * 這個mid半天沒變過*/int mid = (low+high)/2;/*** 判斷它是否等于* * 我們看一下這一步是不是可以省略* 直接進行折半查找就可以了* 是否等于,等于就直接返回* 這是key等于它*/if(key==array[mid]) {return mid;}else if(key<array[mid]) {/*** key小于array[mid],* 就是key是21,你找的是21,* 中間是56,是不是給high,low不用給* */high = mid-1;}else {/*** 這個else意味著一個含義* key>array[mid]*/low = mid + 1; } }/*** 實在找不到先返回-1* * 如果沒找到就返回-1*/return -1;}} package com.learn.search;/*** 這是我們說的折半查找* 折半查找給了大家兩種思路,* 哪兩種思路啊,* 第一個是非遞歸的,* 第二個是遞歸的,* 那非遞歸的告訴我時間復(fù)雜度是多少,* 然后空間復(fù)雜度* S(n) = O(1);* T(n) = O(log2 n)* 不管你循環(huán)了多少次,* 并沒有分配更多的變量,* * 當我們采用的遞歸的話,* 遞歸怎么辦,* 他是不是還是每次減少一半,* 這實現(xiàn)上還是差不多的,* T(n) = O(log2n);* 花的時間是差不多的,* 因為都是每次找一半,* 但是空間復(fù)雜度S(n)呢,* 每一次的空間復(fù)雜度是1,* 但是他這個方法調(diào)用了logn次唄* 我只調(diào)用一次這個方法是有限的,* 可是調(diào)用了log2 n次了,* 所以我們可以讓1*log2n* S(n) = O(1*log2n);* 所以最后就是log2n* S(n) = O(log2 n);* 重復(fù)的調(diào)用,重復(fù)的分配空間,* 這樣他花的空間就比較多的,* 從這個角度來說我們應(yīng)該有哪一個,* 使用非遞歸的,* 那我們怎么還來講一下遞歸的,* 在這個例子來說代碼差不多* 就找這種分析問題的思路,* 擴展一下這種思路,* 也是可以這么來解決的,* 到這里我們就把線性表查找里的順序查找和折半查找給大家講了* 順序查找非常的簡單,折半查找是我們的一個重點,* 首先掌握算法,* 然后能寫出代碼,* 最后一步一定要知道折半查找的時間復(fù)雜度和空間復(fù)雜度* 尤其他的時間復(fù)雜度,logn這個性能非常高的,* * @author Leon.Sun**/ public class TestSearch3 {public static void main(String[] args) {int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };// int key = 2; // int key = 10;int key = 60;// int index = -1;int index = binarySearch(array,key);if(index==-1) {System.out.println("不存在");}else {System.out.println(key + "的索引是" + index);}}/*** 我們要使用遞歸* 大家想一下,剛才我們使用遞歸的話,是什么不一樣* 一樣的是什么,不一樣的是什么,* 這是一次遞歸,這又是一次遞歸,* 這還是一次遞歸,相同的是什么,* 你永遠找到的是21,你找的數(shù)據(jù)永遠在這兒,* 不同的是什么意思,* low和high不一樣,范圍不一樣了* 初始狀態(tài)從0到10* 那么基于這一點的話我們開始寫程序了* 我們要進行這樣的一個查找,* 我們要在這里面找這個值,* @param array* @param key* @return*/public static int binarySearch(int[] array,int key) {int low = 0;int high = array.length - 1;/*** 第一次找的話整個數(shù)組,key是21,low是0,high是最后一個元素* */return binarySearch(array, key, low, high);}/*** 我們增加兩個參數(shù),low和high* 因為每次調(diào)用array和key是相同的,* 但是low和high兩個是一樣的,這兩個是不一樣的* * 怎么來理解,一下子傳入4個參數(shù),* * 每次遞歸array和key都是一樣的,* 不一樣的是low和high* 兩個都相當于指針,* * @param array* @param key* @param low* @param high* @return*/public static int binarySearch(int[] array,int key,int low,int high) {/*** 請問這里面該怎么寫,遞歸* 首先要寫遞歸的結(jié)束條件,* 如果low大于high了,* 你傳進來的low已經(jīng)大于high了,* 那就沒找到唄,* 這是個結(jié)束條件* * low大于high,*/if(low>high) {return -1;}/*** 這是中間* * 獲取mid*/int mid = (low+high)/2;/*** 找到就結(jié)束了*/if(key==array[mid]) {return mid;}else if(key<array[mid]) {/*** key找的是它,* 下面我要重復(fù)剛才的操作唄* 數(shù)據(jù)在array里面放著呢,* 查找的還是key,你現(xiàn)在找的是21,* 現(xiàn)在找到56這里了,我們要在前面的位置找,* low還是0,high等于mid-1,* low沒有變,high=mid-1* * 我們都寫上一個return* * 小于就遞歸查找*/return binarySearch(array, key, low, mid-1);}else {/*** 再來個else,就相當于key>array[mid]* 他在右邊找,* 這是哪個內(nèi)容,21大于19了,* high沒變,low變了,* 還是要進行折半查找,* 那這個時候要怎么辦,* 比如high沒有變,* low變成mid+1,* 別忘了寫了return* * 大于也遞歸查找*/return binarySearch(array, key, mid+1, high);}}}

?

總結(jié)

以上是生活随笔為你收集整理的顺序表查找+折半查找(二级)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。