JAVA-初步认识-第五章-数组-常见操作-查找&折半查找

一. 查找

想要知道某一个数据在数组中的位置。(从一个数组中查找某一个数据,数据存在的话,同时返回角标号,没有相应的数据,返回-1.)

介绍数组常见的操作,实际上就是功能化的函数(求最值,排序,查找)。一旦说到函数,就涉及到两个明确,返回值和输入。这里要得到的是位置,也就是索引号。我们要知道某一个数据在某一个数组中的位置,数据和数组都是不确定的,这是一个通用的解法。编写程序就是用通用的方法,来解决具体的问题,主函数中是确定的问题,功能化函数中是通用的解法。因此,输入中有两个形参。在写形参时,要标注类型和变量名。

时刻要用辩证的思维来看待问题,查找有两种结果,找到和找不到。找的到时,直接返回角标值,找不到时,返回-1。在数组对数据编号时,都是从0开始编的,返回了-1,就表示数组中没有该数据,也不存在相应的角标号。

这里还需要注意的一个问题是,是否对应数据的角标只有一个?原因就在于数组的不确定性,对样性。

这里return -1写在for语句的外面也挺奇怪的。我们来分析一下,(其实这里牵涉return能够返回多个值的问题),从定义方法后,进入for语句。for循环里面,如果if成立,就返回一个。for里面有这么三种情况,有多个返回值,有一个返回值,无返回值。无论for里面是什么情况,接着都会返回一个-1的值。但是数组里面有对应数据的时候,得到的返回值就是第一次出现数据的角标号,后面的返回值都不管,这里值得深思。无论怎样,最后都会返回一个-1的值,如果前面有对应数据,有返回角标值,那么这个-1就无所谓;如果前面没有返回值,那么这里的-1就是唯一的返回值,也就意味着数组中没有对应的数据。

二. 

给定一个确定的数组{4,1,8,7,3,8,2},如果我们利用上面的源代码来查找数据8的位置,结果显示的是第一个8所在的角标2。

这里我产生一个疑问,为什么输出语句最后输出的值不是角标5,是比2后返回,最后的值应该是5才对。我怀疑我对for循环语句理解不对,for循环结构是否对每一个x都执行了?怎么退出的,是全部执行完了退出的,还是满足了某一个x的执行语句才退出的?→循环语句的结束,都是最终不符合循环条件才退出的,和执行语句并无关系。那么,对于这里的两个返回值(其实是三个返回值,-1是一直都要返回的),输出先返回的值,就值得深思了。

int index=getIndex(arr, 8)中方法名为getIndex,可见函数名和类名的起名规则不一样,类名第一个单词的首字母就开始大写了,而函数名要等到第二个单词才行

三. 折半查找

从视频的讲解来看,数据的操作先介绍了查找,又介绍了折半查找。为什么会介绍两种查找,就在于数据的多少不一样,查找的程序是针对数据比较少的情况来的。折半查找是对于数据很多时,设定的源代码。针对数据较多时,为了提高效率,而设计了折半查找。

折半查找可以提高查找的效率。能够执行折半查找的数据有一个必要前提,数据必须是有序的。

折半查找和查找功能是一样的,都是为了在数组中查找某一个数据,并返回它的角标号。只是在具体执行的时候,思路有些不一样,但是方法的输入和返回值都是一样的。

举例说明

下面对于折半查找分了两种情况,一种是有这个数据,另一种是没这个数据。但无论是有无数据的查找,执行语句都应该是相同的。

思路:折半查找时,核心的有两步,折半和对比。折半和对比要进行多次,这就意味着有循环的存在。循环结构的三种语句while,do while,for三者中,视频中采用了while语句,没有采用for语句。这是为什么?两者之间存在什么区别么?按道理来说,三者都是同一种结构的语句,本质上应该是一样的,可能应用的方向不一样。依本题来看,本题也不是不可以采用for,但是如果用for语句,书写起来很麻烦,初始表达式很多,很长,条件表达式和控制循环的条件也很长,不适合用for语句,for适合数字进行循环,数字足够的精简。

接着将思路,初始话表达式中,就必须有一个mid,来和给定数据进行对比,当两者不想等时,就进入循环;如果相等,就直接返回折半值。进入循环后,下一个折半值,以及min和max也要重新确定,这也是对比的情况得来的。对比永远只有一个式子,折半值和给定数据是否相等。进入循环后,肯定要有退出循环的条件,不然循环将一直进行,如果max<min,那么也就意味着没有对应的数据,返回-1。

情况1:

key=45,确定数据45的角标。

开始时,我们要确定中间角标的大小,中间角标=(首角标+尾角标)/2,由于这是java计算机语言中的计算,所以中间角标的结果绝对不会是浮点型,都是int类型。这一连串数据是有大小顺序的,但是并没有规定,相差都为1,思维不能僵硬。

 

情况2:

key=50, 

思考:折半查找中设计几个内容,首先需要三个变量,需要重复地去做中间角标是不是要找的元素,是大还是还是小,然后继续进行折半的动作,这些动作是在重复执行,这就用到了循环。

 自己编写源代码:

DOS运行完的结果完全不对。我们想要的是数据45所在的角标号,这里返回了3,和我们想要的5不符合。回过来仔细研究,循环中即使能够和给定的数据符合,返回的折半值也并非数据的角标值。→理解错误,折半值在整个计算的过程中,一直在某些角标上调整,因为初角标和尾角标都是数组的实际角标。

→在首次进行循环判断的时候,arr[mid]=28,28==45,得出的是false,这样就进不了循环了。我在循环表达式中,写的是==,意味着,两者相等成立时就进入循环体,不等时就不进入循环。视频采用的是!=,这意味着不想等成立时就进入循环,不相等不成立时,就不进入循环。这样一来,我的写法是错误的。

→上面截图中的return mid的理解不对,return mid在循环结构的外面

视频中的有点,我不能理解,if语句有三种格式,没有见过if, else if就结束的语句,按道理来说还有个else。

→还有一点看不明白,当给定的数据不在数组中的时,这里的while语句是怎么退出的?while循环结构的退出,不满足条件表达式就退出。但是arr[mid]肯定永远不等于key,那么就一直在循环里面,难不成return还有其他功能?退出

四. 另一种思路

五.

有一点要注意,折半查找需要排序好的数组,如果是乱的数组,对其先排序,在折半查找,这样做是没什么用的,因为数据被调换了位置。

原文地址:https://www.cnblogs.com/wsw-bk/p/7616834.html