- 蓦松
-
常用的构造哈希(hash)函数的方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数发、随机数法。
1、直接定址法
取关键字或关键字的某个线性函数值为哈希地址。即:H(key)=key或H(key)=akey+b。其中a和b为常数(这种哈希函数叫做自身函数)。
2、数字分析法
假设关键字是以r为基的数(如:以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。
3、平方取中法
取关键字平方后的中间几位为哈希地址。这是一种较常用的构造哈希函数的方法。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关。
4、折叠法
将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址,这方法称为折叠法(folding)。关键字位数很多,而且关键字中每一-位上数字分布大致均匀时,可以采用折叠法得到哈希地址。
5、除留余数发
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即H(key) = key MOD p, pm。这是一种最简单,也最常用的构造哈希函数的方法。它不仅可以对关键字直接取模(MOD),也可在折叠,平方取中等运算之后取模。
6、随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key)=random(key),其中random为随机函数。通常_当关键字长度不等时采用此法构造哈希函数较恰当。
冲突的处理:
哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)=H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址,解决冲突的方法:
1、链接法(拉链法):将具有同一散列地址的记录存储在一条线性链表中。例,除留余数法中,设关键字为(18,14,01,68,27,55,79),除数为13,散列地址为(5,1,1,3,1,3,1)。
2、开放定址法:如果h(k)已经被占用,按如下序列探查:(h(k)+p⑴)%TSize,(h(k)+p⑵)%TSize,?,(h(k)+p(i))%TSize,?其中,h(k)为哈希函数,TSize为哈希表长,p(i)为探查函数。
在h(k)+p(i-1))%TSize的基础上,若发现冲突,则使用增量p(i)进行新的探测,直至无冲突出现为止。
根据探查函数p(i)的不同,开放定址法又分为线性探查法(p(i) = i : 1,2,3,?),二次探查法(p(i)=(-1)^(i-1)*((i+1)/2)^2,探查序列依次为:1, -1,4, -4, 9?)。
随机探查法(p(i):随机数),双散列函数法(双散列函数h(key),hp (key)若h(key)出现冲突,则再使用hp (key)求取散列地址。探查序列为:h(k),h(k)+ hp(k),?,h(k)+ i*hp(k))。
3、桶定址法:桶为一片足够大的存储空间。桶定址为表中的每个地址关联一个桶。如果桶已经满了,可以使用开放定址法来处理。例如,插入A5,A2,A3,B5,A9,B2,B9,C2,采用线性探查法解决冲突。
相关推荐
线性探查法是什么概念
线性探查法(Linear Probing)该方法的基本思想是:将散列表T[0..m-1]看成是一个循环向量,若初始探查的地址为d(即h(key)=d),则最长的探查序列为:d,d+l,d+2,…,m-1,0,1,…,d-1即:探查时从地址d开始,首先探查T[d],然后依次探查T[d+1],…,直到T[m-1],此后又循环到T[0],T[1],…,直到探查到T[d-1]为止.2023-11-20 05:07:101
设散列函数为h(k)=k mod 7用线性探查法解决碰撞。现从空的散列表开始,依次插入关键码23,14,9,6,30,12,18
散列函数是一种将输入数据映射到散列表中位置的方法。在这个问题中,散列函数h(k)=k mod 7 将输入的键k取余数后,将其映射到一个0到6之间的位置。线性探查法是解决散列碰撞问题的一种方法。当两个不同的键被映射到相同的位置时,就会发生碰撞。为了解决碰撞,我们需要在散列表中找到下一个可用的位置。线性探查法通过顺序检查下一个位置,直到找到一个空闲位置来解决碰撞。让我们从一个空的散列表开始,假设我们有以下键值对需要插入:{12, 18, 27, 8, 41, 36, 45}。我们将第一个键值对12插入散列表中。由于h(12)=5,我们将12插入位置5处。接下来,我们插入18。由于h(18)=4,位置4已经被占用了。根据线性探查法,我们需要顺序检查下一个位置。h(18)+1=5也被占用了,所以继续检查下一个位置,h(18)+2=6是空闲的,于是我们将18插入位置6处。然后是27。由于h(27)=6,位置6已经被占用了,继续检查下一个位置。h(27)+1=0是空闲的,所以我们将27插入位置0处。接下来是8。由于h(8)=1,位置1已经被占用了,继续检查下一个位置。h(8)+1=2也被占用了,继续检查下一个位置。h(8)+2=3是空闲的,于是我们将8插入位置3处。然后是41。由于h(41)=6,位置6已经被占用了,继续检查下一个位置。h(41)+1=0也被占用了,继续检查下一个位置。h(41)+2=1也被占用了,继续检查下一个位置。h(41)+3=2也被占用了,继续检查下一个位置。h(41)+4=3也被占用了,最后一个位置 h(41)+5=4 是空闲的,所以我们将41插入位置4处。然后是36。由于h(36)=1,位置1已经被占用了,继续检查下一个位置。h(36)+1=2也被占用了,继续检查下一个位置。h(36)+2=3也被占用了,继续检查下一个位置。h(36)+3=4也被占用了,继续检查下一个位置。h(36)+4=5也被占用了,继续检查下一个位置。h(36)+5=6也被占用了,最后一个位置 h(36)+6=0 是空闲的,所以我们将36插入位置0处。最后是45。由于h(45)=3,位置3已经被占用了,继续检查下一个位置。h(45)+1=4也被占用了,继续检查下一个位置。h(45)+2=5也被占用了,继续检查下一个位置。h(45)+3=6也被占用了,继续检查下一个位置。h(45)+4=0也被占用了,继续检查下一个位置。h(45)+5=1也被占用了,最后一个位置 h(45)+6=2 是空闲的,所以我们将45插入位置2处。至此,所有的键值对都已经成功插入到散列表中。总结一下,通过线性探查法解决碰撞的过程就是顺序检查下一个位置直到找到空闲位置为止。虽然线性探查法简单易实现,但当散列表发生冲突时会导致聚集现象,并且删除操作较为复杂。因此,在实际应用中需要根据具体情况选择更适合的解决碰撞的方法。感谢您的阅读,希望对您有所帮助!2023-11-20 05:07:173
假设有k个关键字互为同义词,若用线性探查法把这k个关键字存入,至少要进行的探查次数是()。
【答案】:D假设有k个关键字互为同义词,若用线性探查法把这k个关键字存入,探查次数最少的情况是第1个关键字通过1次比较后插入,第2个关键字通过2次比较后插入,…,第k个关键字通过k次比较后插入。总的比较次数=1+2+…+k=k(k+1)/2。2023-11-20 05:07:241
散列查找的处理冲突的方法
思路:从发生冲突的那个单元开始,按照一定次序,从散列表中查找出一个空闲的存储单元,把发生冲突的待插入元素存入到该单元的一类处理冲突的方法。在使用该方法处理冲突的散列表中,查找一个元素的过程是:先根据给定关键字K,利用与插入时使用的同一散列函数h(K)计算出散列地址(设下标为d),然后用K同d单元的关键字比较,若相等则查找成功,否则按插入时处理冲突的相同次序,依次用K同所查单元的关键字比较,直到查找成功或查找到一空单元(表明查找失败)为止。有三种常见的开放定址法(1)线性探查法是用开放定址法处理冲突的一种最简单的探查方法。从发生冲突的d单元起,依次探查下一个单元,直到碰到一个空闲单元或探查完所有单元为止探查时,当达到下标为m-1的表尾单元时,下一个探查的单元是下标为0的表首单元。探查序列为d,d+1,d+2……,表示为(d+i)%m (0≤i≤m-1)。例如:构取m=13,线性表为A=(18,75,60,43,54,90,46),构造的散列表如下: 0 1 2 3 4 5 6 7 8 9 10 11 12 H 54 43 18 46 60 75 90 现向表中再插入关键字为31和58的两个元素,用线性探查法解决冲突。先插入31,h(31)=31%13=5,因H[5]被占用,探查下一个即下标为6的单元,空闲,插入31。 0 1 2 3 4 5 6 7 8 9 10 11 12 H 54 43 18 31 46 60 75 90 再插入58,h(58)=58%13=6,因H[6]被占用,探查下一个即下标为7的单元,因H[7]仍不空闲,再接着向下探查,当探查到下标为9的单元时,空闲,插入58。 0 1 2 3 4 5 6 7 8 9 10 11 12 H 54 43 18 31 46 60 58 75 90 利用线性探查法处理冲突易造成元素的“堆积”(聚集) 0 1 2 3 4 5 6 7 8 9 10 11 12 H 54 43 18 46 60 75 90 向散列表中插入一个元素:int Insert (hashlist1 HT,int m,ElemType item){//向长度为m的散列表HT中插入一个元素int d=H(item.key,m); //可选一种合适的构造散列函数的方法,计算散列地址int temp=d;while(HT[d].key != NullTag){//当d单元不空时继续向后查找空位置d=(d+1)%m;if(d==temp) return 0;}HT[d]=item; //将新元素插入到下标为d的位置return 1;}从散列表中查找一个元素:int Search (hashlist1 HT,int m, ElemType item){//从长度为m的散列表HT中查找int d=H(item.key, m);int temp=d;while(HT[d].key!=NullTag){//当散列地址中的关键字域不为空则循环if(HT[d].key==item.key) return d;else d=(d+1)%m;if(d==temp) return -1;}return -1;}(2)平方探查法探查序列为d,d+1,d+2……,表示为(d+i2)%m(0≤i≤m-1)。递推公式为:优点:它是一种较好的处理冲突的方法,可以较好避免堆积现象缺点:不能探查到散列表上所有单元。例:当d0=5,m=17时,只能探查到下标依次为5、6、9、14、4、13、7、3、1的单元。d0=5;d1=(5 +2*1-1)%17=6; d2=(6 +2*2-1)%17=9;d3=(9 +2*3-1)%17=14; d4=(14 +2*4-1)%17=4;d5=(4 +2*5-1)%17=13; d6=(13 +2*6-1)%17=7;d7=(7 +2*7-1)%17=3; d8=(3 +2*8-1)%17=1; d9=(1 +2*9-1)%17=1;(3)双散列函数探查法思路:该方法使用两个散列函数h1和h2,其中h1和前面的h(K)一样,以关键字为自变量,产生一个0~m-1之间的数作散列地址;h2也以关键字为自变量,产生一个1~m-1之间的、并和m互素的数作散列地址。它的探查序列为:利用双散列法,按一定的距离,跳跃式地寻找“下一个”桶,减少了“堆积”的机会,最多经过m-1次探查,它会遍历表中所有位置,回到H0 位置。例:给出一组表项关键码{22,41,53,46,30,13,01,67}。散列表为HT[0..10],m = 11。散列函数为:Hash(x)=(3x) % 11再散列函数为:ReHash(x) = (7x) % 10 +1Hi = ( Hi-1 uf0bc+ (7x) % 10 +1 ) % 11, i = 1, 2,H0(22) = 0 H0(41) = 2 H0(53) = 5 H0(46) = 6H0(30) = 2 冲突H1 = (2+1) = 3 ,H0(13) = 6 冲突H1 = (6+2) = 8H0(01) = 3 冲突H1 = (3+8) = 0 ,H2 = (0+8) = 8 H3 = (8+8) = 5H4 =(5+8)=2 H5 =(2+8)=10,H0(67)=3 冲突, H1 = (3+10) = 2 H2 = (2+10) = 1搜索成功的平均搜索长度:链接法思路:就是把发生冲突的同义词元素(结点)用单链表链接起来的方法。例:假定一个线性表B为:B=(18,75,60,43,54,90,46,31,58,73,15,34)。设采用的散列函数为h(K)=K%13,采用链接法处理:在该例中,查找成功时平均查找长度为:ASL=(8×1+3×2+1×3)/12≈1.42若线性探查法处理冲突进行散列存储,得到:查找成功时平均查找长度为:ASL=(7×1+1×2+1×4+1×4+1×2+1×6)/12≈2.1多种方法分析在散列表的插入和查找算法中,平均查找长度与表的大小m无关,只与选取的散列函数、α值和处理冲突的方法有关,若假定所选取的散列函数能够使任一关键字等概率地映射到散列空间的任一地址上,理论上证明:当采用线性探查法处理冲突时,ASL=当采用链地址法处理冲突时,ASL=当采用平方探查法、双散列函数法处理冲突时,ASL=散列存储优缺点插入与查找的速度相当快根据关键字计算散列地址需要开销一定计算时间占用存储空间较多在散列表中只能按关键字查找元素线性表中元素的逻辑关系无法在散列表中体现。 链表地址法为散列表的每个表象建立一个单链表,用于链接同义词表,为此需要给每个表项增加一个指针域。关于同义词表的建立,有两种方法。一种方法是在散列表的基本存储区域外开辟一个新的区域用于存储同义词表,这种方法称为“分离的同义词子表法”,或称“独立链表地址法”,这个分离的同义词子表所在的区域称为“溢出区”。另一种方法是不建立溢出区,而是将同义词子表存储在散列表所在的基本存储区域里,例如,可以再基本存储区域里从后向前探测空闲表项,找到后就将其链接到同义词子表中,这个方法称为“结合的同义词子表法”,或称为“公共链表地址法”。独立链表地址法是查找效率最好的解决冲突的方法,速度要快于开放地址法,因为独立链表地址法在进行散列查找时仅需搜索同义词表。开放地址法要求表长时固定的,而地理链表法中的表项则是动态分配的,其表长仅受内存空间的限制。链表法的主要缺点是需要为每个表项(包括分离的同义子表的每个节点)设立一个指针域。总之,独立链表地址法的动态结构使它成为散列法中解决冲突的首选方法。2023-11-20 05:07:311
查找 - 散列技术 - 处理冲突的方法(二)
利用线性探测法构造散列表 【例 】已知一组关键字为( ) 用除余法构造散列函数 用线性探查法解决冲突构 造这组关键字的散列表 解答:为了减少冲突 通常令装填因子α <l。.lishixinzhi这里关键字个数n=10,不妨取m=13,此时α≈0.77,散列表为t[0..12],散列函 p=""> </l。.lishixinzhi这里关键字个数n=10,不妨取m=13,此时α≈0.77,散列表为t[0..12],散列函> 数为:h(key)=key%13。 由除余法的散列函数计算出的上述关键字序列的散列地址为(0,10,2,12,5,2,3,12,6,12)。 前5个关键字插入时,其相应的地址均为开放地址,故将它们直接插入T[0],T[10),T[2],T[12]和T[5]中。 当插入第6个关键字15时,其散列地址2(即h(15)=15%13=2)已被关键字41(15和41互为同义词)占用。故探查h1=(2+1)%13=3, 此地址开放,所以将15放入T[3]中。 当插入第7个关键字68时,其散列地址3已被非同义词15先占用,故将其插入到T[4]中。 当插入第8个关键字12时,散列地址12已被同义词38占用,故探查hl=(12+1)%13=0,而T[0]亦被26占用,再探查h2=(12+2)% 13=1,此地址开放,可将12插入其中。 类似地,第9个关键字06直接插入T[6]中;而最后一个关键字51插人时,因探查的地址12,0,1,…,6均非空,故51插入 T[7]中。 构造散列表的具体过程【 参见动画演示 】 聚集或堆积现象 用线性探查法解决冲突时,当表中i,i+1,…,i+k的位置上已有结点时,一个散列地址为i,i+1,…,i+k+1的结点都将插入在 位置i+k+1上。把这种散列地址不同的结点争夺同一个后继散列地址的现象称为聚集或堆积(Clustering)。这将造成不是同义词的结 点也处在同一个探查序列之中,从而增加了探查序列的长度,即增加了查找时间。若散列函数不好或装填因子过大,都会使堆积现象 加剧。 【例】上例中,h(15)=2,h(68)=3,即15和68不是同义词。但由于处理15和同义词41的冲突时,15抢先占用了T[3],这就使 得插入68时,这两个本来不应该发生冲突的非同义词之间也会发生冲突。 为了减少堆积的发生,不能像线性探查法那样探查一个顺序的地址序列(相当于顺序查找),而应使探查序列跳跃式地散列在整个 散列表中。 ②二次探查法(Quadratic Probing) 二次探查法的探查序列是: h i =(h(key)+i*i)%m 0≤i≤m-1 //即d i =i 2 即探查序列为d=h(key),d+1 2 ,d+2 2 ,…,等。 该方法的缺陷是不易探查到整个散列空间。 ③双重散列法(Double Hashing) 该方法是开放定址法中最好的方法之一,它的探查序列是: h i =(h(key)+i*h1(key))%m 0≤i≤m-1 //即d i =i*h1(key) 即探查序列为: d=h(key),(d+h1(key))%m,(d+2h1(key))%m,…,等。 该方法使用了两个散列函数h(key)和h1(key),故也称为双散列函数探查法。 注意: 定义h1(key)的方法较多,但无论采用什么方法定义,都必须使h1(key)的值和m互素,才能使发生冲突的同义词地址均匀地分布 在整个表中,否则可能造成同义词地址的循环计算。 【例】 若m为素数,则h1(key)取1到m-1之间的任何数均与m互素,因此,我们可以简单地将它定义为: h1(key)=key%(m-2)+1 【例】对例9.1,我们可取h(key)=key%13,而h1(key)=key%11+1。 【例】若m是2的方幂,则h1(key)可取1到m-1之间的任何奇数。 2、拉链法 (1)拉链法解决冲突的方法 拉链法解决冲突的做法是:将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m,则可将散列表定义为 一个由m个头指针组成的指针数组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均 应为空指针。在拉链法中,装填因子α可以大于1,但一般均取α≤1。 【例9.2】已知一组关键字和选定的散列函数和例9.1相同,用拉链法解决冲突构造这组关键字的散列表。 解答:不妨和例9.1类似,取表长为13,故散列函数为h(key)=key%13,散列表为T[0..12]。 注意: 当把h(key)=i的关键字插入第i个单链表时,既可插入在链表的头上,也可以插在链表的尾上。这是因为必须确定key不在第i个 链表时,才能将它插入表中,所以也就知道链尾结点的地址。若采用将新关键字插入链尾的方式,依次把给定的这组关键字插入表中 ,则所得到的散列表 具体构造过程【 参见动画演示 】。 (2)拉链法的优点 与开放定址法相比,拉链法有如下几个优点: (1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短; (2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况; (3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大 时,拉链法中增加的指针域可忽略不计,因此节省空间; (4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散 列表,删除结点不能简单地将被删结点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放 地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点 上做删除标记,而不能真正删除结点。 (3)拉链法的缺点 拉链法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列 表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。 lishixinzhi/Article/program/sjjg/201311/236772023-11-20 05:07:451
线性探测法表长如何确定
线性探测法表长确定需要用该方法一次探测下一个地址,知道有空的地址后插入,若整个空间都找不到空余的地址,则产生溢出。2023-11-20 05:07:521
hash函数的构造方法
常用的构造哈希(hash)函数的方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数发、随机数法。1、直接定址法取关键字或关键字的某个线性函数值为哈希地址。即:H(key)=key或H(key)=akey+b。其中a和b为常数(这种哈希函数叫做自身函数)。2、数字分析法假设关键字是以r为基的数(如:以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。3、平方取中法取关键字平方后的中间几位为哈希地址。这是一种较常用的构造哈希函数的方法。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关。4、折叠法将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址,这方法称为折叠法(folding)。关键字位数很多,而且关键字中每一-位上数字分布大致均匀时,可以采用折叠法得到哈希地址。5、除留余数发取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即H(key) = key MOD p, pm。这是一种最简单,也最常用的构造哈希函数的方法。它不仅可以对关键字直接取模(MOD),也可在折叠,平方取中等运算之后取模。6、随机数法选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key)=random(key),其中random为随机函数。通常﹐当关键字长度不等时采用此法构造哈希函数较恰当。冲突的处理:哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)=H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址,解决冲突的方法:1、链接法(拉链法):将具有同一散列地址的记录存储在一条线性链表中。例,除留余数法中,设关键字为(18,14,01,68,27,55,79),除数为13,散列地址为(5,1,1,3,1,3,1)。2、开放定址法:如果h(k)已经被占用,按如下序列探查:(h(k)+p⑴)%TSize,(h(k)+p⑵)%TSize,…,(h(k)+p(i))%TSize,…其中,h(k)为哈希函数,TSize为哈希表长,p(i)为探查函数。在h(k)+p(i-1))%TSize的基础上,若发现冲突,则使用增量p(i)进行新的探测,直至无冲突出现为止。根据探查函数p(i)的不同,开放定址法又分为线性探查法(p(i) = i : 1,2,3,…),二次探查法(p(i)=(-1)^(i-1)*((i+1)/2)^2,探查序列依次为:1, -1,4, -4, 9…)。随机探查法(p(i):随机数),双散列函数法(双散列函数h(key),hp (key)若h(key)出现冲突,则再使用hp (key)求取散列地址。探查序列为:h(k),h(k)+ hp(k),…,h(k)+ i*hp(k))。3、桶定址法:桶为一片足够大的存储空间。桶定址为表中的每个地址关联一个桶。如果桶已经满了,可以使用开放定址法来处理。例如,插入A5,A2,A3,B5,A9,B2,B9,C2,采用线性探查法解决冲突。2023-11-20 05:08:001
数据结构课程中,散列表里的线性探查法中不成功的平均查找长度怎么求
举个例子吧 数组长度10 散列函数x%7如 13 先计算散列 13%7 = 6 如果没有冲突的话会被放在第六个格子里现在散列表中 : (x为已经有一个元素 o表示空)0 x1 x2 x3 o4 o5 x6 x7 x8 x9 o计算失败概率 : 思路如下,任意出现一个数字(概率均等)经过hash函数以后 0 ~ 6的概率均等 现在假设 输入一个数字 hash计算结果是1,去1里查找,结果发现位置1(接下来简称pos1)不是目标元素(查找失败),于是线性探查找到了2(还是失败)然后找三,发现没有,于是确定所找元素不在哈希表里,以上是查找过程,以此类推失败的情况下需要找 4,3,2,1,1,5,4 (7和7以后没得找,因为任何数膜7都<7)失败概率~~~自己算吧~2023-11-20 05:08:161
hash算法原理详解
散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存入到此存储单元中。检索时,用同样的方法计算地址,然后到相应的单元里去取要找的结点。通过散列方法可以对结点进行快速检索。散列(hash,也称“哈希”)是一种重要的存储方式,也是一种常见的检索方法。 按散列存储方式构造的存储结构称为散列表(hash table)。散列表中的一个位置称为槽(slot)。散列技术的核心是散列函数(hash function)。 对任意给定的动态查找表DL,如果选定了某个“理想的”散列函数h及相应的散列表HT,则对DL中的每个数据元素X。函数值h(X.key)就是X在散列表HT中的存储位置。插入(或建表)时数据元素X将被安置在该位置上,并且检索X时也到该位置上去查找。由散列函数决定的存储位置称为散列地址。 因此,散列的核心就是:由散列函数决定关键码值(X.key)与散列地址h(X.key)之间的对应关系,通过这种关系来实现组织存储并进行检索。 一般情况下,散列表的存储空间是一个一维数组HT[M],散列地址是数组的下标。设计散列方法的目标,就是设计某个散列函数h,0<=h( K ) < M;对于关键码值K,得到HT[i] = K。 在一般情况下,散列表的空间必须比结点的集合大,此时虽然浪费了一定的空间,但换取的是检索效率。设散列表的空间大小为M,填入表中的结点数为N,则称为散列表的负载因子(load factor,也有人翻译为“装填因子”)。建立散列表时,若关键码与散列地址是一对一的关系,则在检索时只需根据散列函数对给定值进行某种运算,即可得到待查结点的存储位置。但是,散列函数可能对于不相等的关键码计算出相同的散列地址,我们称该现象为冲突(collision),发生冲突的两个关键码称为该散列函数的同义词。在实际应用中,很少存在不产生冲突的散列函数,我们必须考虑在冲突发生时的处理办法。 在以下的讨论中,我们假设处理的是值为整型的关键码,否则我们总可以建立一种关键码与正整数之间的一一对应关系,从而把该关键码的检索转化为对与其对应的正整数的检索;同时,进一步假定散列函数的值落在0到M-1之间。散列函数的选取原则是:运算尽可能简单;函数的值域必须在散列表的范围内;尽可能使得结点均匀分布,也就是尽量让不同的关键码具有不同的散列函数值。需要考虑各种因素:关键码长度、散列表大小、关键码分布情况、记录的检索频率等等。下面我们介绍几种常用的散列函数。 顾名思义,除余法就是用关键码x除以M(往往取散列表长度),并取余数作为散列地址。除余法几乎是最简单的散列方法,散列函数为: h(x) = x mod M。 使用此方法时,先让关键码key乘上一个常数A (0< A < 1),提取乘积的小数部分。然后,再用整数n乘以这个值,对结果向下取整,把它做为散列的地址。散列函数为: hash ( key ) = _LOW( n × ( A × key % 1 ) )。 其中,“A × key % 1”表示取 A × key 小数部分,即: A × key % 1 = A × key - _LOW(A × key), 而_LOW(X)是表示对X取下整 由于整数相除的运行速度通常比相乘要慢,所以有意识地避免使用除余法运算可以提高散列算法的运行时间。平方取中法的具体实现是:先通过求关键码的平方值,从而扩大相近数的差别,然后根据表长度取中间的几位数(往往取二进制的比特位)作为散列函数值。因为一个乘积的中间几位数与乘数的每一数位都相关,所以由此产生的散列地址较为均匀。 假设关键字集合中的每个关键字都是由 s 位数字组成 (u1, u2, …, us),分析关键字集中的全体,并从中提取分布均匀的若干位或它们的组合作为地址。数字分析法是取数据元素关键字中某些取值较均匀的数字位作为哈希地址的方法。即当关键字的位数很多时,可以通过对关键字的各位进行分析,丢掉分布不均匀的位,作为哈希值。它只适合于所有关键字值已知的情况。通过分析分布情况把关键字取值区间转化为一个较小的关键字取值区间。 举个例子:要构造一个数据元素个数n=80,哈希长度m=100的哈希表。不失一般性,我们这里只给出其中8个关键字进行分析,8个关键字如下所示: K1=61317602 K2=61326875 K3=62739628 K4=61343634 K5=62706815 K6=62774638 K7=61381262 K8=61394220 分析上述8个关键字可知,关键字从左到右的第1、2、3、6位取值比较集中,不宜作为哈希地址,剩余的第4、5、7、8位取值较均匀,可选取其中的两位作为哈希地址。设选取最后两位作为哈希地址,则这8个关键字的哈希地址分别为:2,75,28,34,15,38,62,20。 此法适于:能预先估计出全体关键字的每一位上各种数字出现的频度。 将关键码值看成另一种进制的数再转换成原来进制的数,然后选其中几位作为散列地址。 例Hash(80127429)=(80127429)13=8 137+0 136+1 135+2 134+7 133+4 132+2*131+9=(502432641)10如果取中间三位作为哈希值,得Hash(80127429)=432 为了获得良好的哈希函数,可以将几种方法联合起来使用,比如先变基,再折叠或平方取中等等,只要散列均匀,就可以随意拼凑。 有时关键码所含的位数很多,采用平方取中法计算太复杂,则可将关键码分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为散列地址,这方法称为折叠法。 分为: 尽管散列函数的目标是使得冲突最少,但实际上冲突是无法避免的。因此,我们必须研究冲突解决策略。冲突解决技术可以分为两类:开散列方法( open hashing,也称为拉链法,separate chaining )和闭散列方法( closed hashing,也称为开地址方法,open addressing )。这两种方法的不同之处在于:开散列法把发生冲突的关键码存储在散列表主表之外,而闭散列法把发生冲突的关键码存储在表中另一个槽内。 (1)拉链法 开散列方法的一种简单形式是把散列表中的每个槽定义为一个链表的表头。散列到一个特定槽的所有记录都放到这个槽的链表中。图9-5说明了一个开散列的散列表,这个表中每一个槽存储一个记录和一个指向链表其余部分的指针。这7个数存储在有11个槽的散列表中,使用的散列函数是h(K) = K mod 11。数的插入顺序是77、7、110、95、14、75和62。有2个值散列到第0个槽,1个值散列到第3个槽,3个值散列到第7个槽,1个值散列到第9个槽。 闭散列方法把所有记录直接存储在散列表中。每个记录关键码key有一个由散列函数计算出来的基位置,即h(key)。如果要插入一个关键码,而另一个记录已经占据了R的基位置(发生碰撞),那么就把R存储在表中的其它地址内,由冲突解决策略确定是哪个地址。 闭散列表解决冲突的基本思想是:当冲突发生时,使用某种方法为关键码K生成一个散列地址序列d0,d1,d2,... di ,...dm-1。其中d0=h(K)称为K的基地址地置( home position );所有di(0< i< m)是后继散列地址。当插入K时,若基地址上的结点已被别的数据元素占用,则按上述地址序列依次探查,将找到的第一个开放的空闲位置di作为K的存储位置;若所有后继散列地址都不空闲,说明该闭散列表已满,报告溢出。相应地,检索K时,将按同值的后继地址序列依次查找,检索成功时返回该位置di ;如果沿着探查序列检索时,遇到了开放的空闲地址,则说明表中没有待查的关键码。删除K时,也按同值的后继地址序列依次查找,查找到某个位置di具有该K值,则删除该位置di上的数据元素(删除操作实际上只是对该结点加以删除标记);如果遇到了开放的空闲地址,则说明表中没有待删除的关键码。因此,对于闭散列表来说,构造后继散列地址序列的方法,也就是处理冲突的方法。 形成探查的方法不同,所得到的解决冲突的方法也不同。下面是几种常见的构造方法。 (1)线性探测法 将散列表看成是一个环形表,若在基地址d(即h(K)=d)发生冲突,则依次探查下述地址单元:d+1,d+2,......,M-1,0,1,......,d-1直到找到一个空闲地址或查找到关键码为key的结点为止。当然,若沿着该探查序列检索一遍之后,又回到了地址d,则无论是做插入操作还是做检索操作,都意味着失败。 用于简单线性探查的探查函数是: p(K,i) = i 例9.7 已知一组关键码为(26,36,41,38,44,15,68,12,06,51,25),散列表长度M= 15,用线性探查法解决冲突构造这组关键码的散列表。 因为n=11,利用除余法构造散列函数,选取小于M的最大质数P=13,则散列函数为:h(key) = key%13。按顺序插入各个结点: 26: h(26) = 0,36: h(36) = 10, 41: h(41) = 2,38: h(38) = 12, 44: h(44) = 5。 插入15时,其散列地址为2,由于2已被关键码为41的元素占用,故需进行探查。按顺序探查法,显然3为开放的空闲地址,故可将其放在3单元。类似地,68和12可分别放在4和13单元中. (2)二次探查法 二次探查法的基本思想是:生成的后继散列地址不是连续的,而是跳跃式的,以便为后续数据元素留下空间从而减少聚集。二次探查法的探查序列依次为:12,-12,22 ,-22,...等,也就是说,发生冲突时,将同义词来回散列在第一个地址的两端。求下一个开放地址的公式为: (3)随机探查法 理想的探查函数应当在探查序列中随机地从未访问过的槽中选择下一个位置,即探查序列应当是散列表位置的一个随机排列。但是,我们实际上不能随机地从探查序列中选择一个位置,因为在检索关键码的时候不能建立起同样的探查序列。然而,我们可以做一些类似于伪随机探查( pseudo-random probing )的事情。在伪随机探查中,探查序列中的第i个槽是(h(K) + ri) mod M,其中ri是1到M - 1之间数的“随机”数序列。所有插入和检索都使用相同的“随机”数。探查函数将是 p(K,i) = perm[i - 1], 这里perm是一个长度为M - 1的数组,它包含值从1到M – 1的随机序列。 例子: 例如,已知哈希表长度m=11,哈希函数为:H(key)= key % 11,则H(47)=3,H(26)=4,H(60)=5,假设下一个关键字为69,则H(69)=3,与47冲突。如果用线性探测再散列处理冲突,下一个哈希地址为H1=(3 + 1)% 11 = 4,仍然冲突,再找下一个哈希地址为H2=(3 + 2)% 11 = 5,还是冲突,继续找下一个哈希地址为H3=(3 + 3)% 11 = 6,此时不再冲突,将69填入5号单元,参图8.26 (a)。如果用二次探测再散列处理冲突,下一个哈希地址为H1=(3 + 12)% 11 = 4,仍然冲突,再找下一个哈希地址为H2=(3 - 12)% 11 = 2,此时不再冲突,将69填入2号单元,参图8.26 (b)。如果用伪随机探测再散列处理冲突,且伪随机数序列为:2,5,9,……..,则下一个哈希地址为H1=(3 + 2)% 11 = 5,仍然冲突,再找下一个哈希地址为H2=(3 + 5)% 11 = 8,此时不再冲突,将69填入8号单元,参图8.26 (c)。 (4)双散列探查法 伪随机探查和二次探查都能消除基本聚集——即基地址不同的关键码,其探查序列的某些段重叠在一起——的问题。然而,如果两个关键码散列到同一个基地址,那么采用这两种方法还是得到同样的探查序列,仍然会产生聚集。这是因为伪随机探查和二次探查产生的探查序列只是基地址的函数,而不是原来关键码值的函数。这个问题称为二级聚集( secondary clustering )。 为了避免二级聚集,我们需要使得探查序列是原来关键码值的函数,而不是基位置的函数。双散列探查法利用第二个散列函数作为常数,每次跳过常数项,做线性探查。2023-11-20 05:08:231
有250个关键字存到散列表中,用线性探查法解决冲突,查找时比较次数不超过3次,该散列至少有多少存储空间
线性探查再散列的查找成功的平均查找长度的理论值为(1+ 1/(1-a))/2,按照你的要求小于3,得到装填因子a <= 4/5,为0.8,因此存储空间约为250/0.8 = 312.5,上取整为3132023-11-20 05:08:291
自考《数据结构》各章要点(2)
第六章 树 树是n个结点的有限集合,非空时必须满足:只有一个称为根的结点;其余结点形成m个不相交的子集,并称根的子树。 根是开始结点;结点的子树数称度;度为0的结点称叶子(终端结点);度不为0的结点称分支结点(非终端结点);除根外的分支结点称内部结点; 有序树是子树有左,右之分的树;无序树是子树没有左,右之分的树;森林是m个互不相交的树的集合; 树的四种不同表示方法:·树形表示法;·嵌套集合表示法;·凹入表示法·广义表表示法。 二叉树的定义:是n≥0个结点的有限集,它是空集(n=0)或由一个根结点及两棵互不相交的分别称作这个根的左子树和右子树的二叉树组成。 二叉树不是树的特殊情形,与度数为2的有序树不同。 二叉树的4个重要性质: ·。二叉树上第i层上的结点数目最多为2^(i-1)(i≥1)。; ·深度为k的二叉树至多有(2^k)-1个结点(k≥1); ·。在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1; ·。具有n个结点的完全二叉树的深度为int(log2n)+1. 满二叉树是一棵深度为k,结点数为(2^k)-1的二叉树;完全二叉树是满二叉树在最下层自右向左去处部分结点; 二叉树的顺序存储结构就是把二叉树的所有结点按照层次顺序存储到连续的存储单元中。(存储前先将其画成完全二叉树) 树的存储结构多用的是链式存储。BinTNode的结构为lchild|data|rchild,把所有BinTNode类型的结点,加上一个指向根结点的BinTree型头指针就构成了二叉树的链式存储结构,称为二叉链表。它就是由根指针root确定的。共有2n个指针域,n+1个空指针。 根据访问结点的次序不同可得三种遍历:先序遍历(前序遍历或先根遍历),中序遍历(或中根遍历)、后序遍历(或后根遍历)。时间复杂度为O(n)。 利用二叉链表中的n+1个空指针域来存放指向某种遍历次序下的前趋结点和后继结点的指针,这些附加的指针就称为“线索”,加上线索的二叉链表就称为线索链表。线索使得查找中序前趋和中序后继变得简单有效,但对于查找指定结点的前序前趋和后序后继并没有什么作用。 树和森林及二叉树的转换是对应的。 转换方法: ·树变二叉树:兄弟相连,保留长子的连线。 ·二叉树变树:结点的右孩子与其双亲连。 ·森林变二叉树:树变二叉树,各个树的根相连。 树的存储结构:·有双亲链表表示法:结点data | parent,对于求指定结点的双亲或祖先十分方便,但不适于求指定结点的孩子及后代。 ·孩子链表表示法:为树中每个结点data | next设置一个孩子链表firstchild,并将data | firstchild存放在一个向量中。 ·双亲孩子链表表示法:将双亲链表和孩子链表结合。 ·孩子兄弟链表表示法:结点结构leftmostchild |data | rightsibing,附加两个分别指向该结点的最左孩子和右邻兄弟的指针域。 树的前序遍历与相对应的二叉树的前序遍历一致;树的后序遍历与相对应的二叉树的中序遍历一致。 树的带权路径长度是树中所有叶结点的带权路径长度之和。树的带权路径长度最小的二叉树就称为二叉树(即哈夫曼树)。 在叶子的权值相同的二叉树中,完全二叉树的路径长度最短。 哈夫曼树有n个叶结点,共有2n-1个结点,没有度为1的结点,这类树又称为严格二叉树。 变长编码技术可以使频度高的字符编码短,而频度低的字符编码长,但是变长编码可能使解码产生二义性。如00、01、0001这三个码无法在解码时确定是哪一个,所以要求在字符编码时任一字符的编码都不是其他字符编码的前缀,这种码称为前缀码(其实是非前缀码)。 哈夫曼树的应用最广泛地是在编码技术上,它能够容易地求出给定字符集及其概率分布的前缀码。哈夫曼编码的构造很容易,只要画好了哈夫曼树,按分支情况在左路径上写代码0,右路径上写代码1,然后从上到下到叶结点的相应路径上的代码的序列就是该结点的前缀码。 第七章 图 图的逻辑结构特征就是其结点(顶点)的前趋和后继的个数都是没有限制的,即任意两个结点之间之间都可能相关。 图GraphG=(V,E),V是顶点的有穷非空集合,E是顶点偶对的有穷集。 有向图Digraph:每条边有方向;无向图Undigraph:每条边没有方向。 有向完全图:具有n*(n-1)条边的有向图;无向完全图:具有n*(n-1)/2条边的无向图; 有根图:有一个顶点有路径到达其它顶点的有向图;简单路径:是经过顶点不同的路径;简单回路是开始和终端重合的简单路径; 网络:是带权的图。 图的存储结构: ·邻接矩阵表示法:用一个n阶方阵来表示图的结构是的,适合稠密图。 ·无向图:邻接矩阵是对称的。 ·有向图:行是出度,列是入度。 建立邻接矩阵算法的时间是O(n+n^2+e),其时间复杂度为O(n^2) ·邻接表表示法:用顶点表和邻接表构成不是的,适合稀疏图。·顶点表结构 vertex | firstedge,指针域存放邻接表头指针。 ·邻接表:用头指针确定。 ·无向图称边表; ·有向图又分出边表和逆邻接表; ·邻接表结点结构为 adjvex | next, 时间复杂度为O(n+e)。,空间复杂度为O(n+e)。。 图的遍历: ·深度优先遍历:借助于邻接矩阵的列。使用栈保存已访问结点。 ·广度优先遍历:借助于邻接矩阵的行。使用队列保存已访问结点。 生成树的定义:若从图的某个顶点出发,可以系统地访问到图中所有顶点,则遍历时经过的边和图的所有顶点所构成的子图称作该图的生成树。 最小生成树:图的生成树不,从不同的顶点出发可得到不同的生成树,把权值最小的生成树称为最小生成树(MST)。 构造最小生成树的算法: ·Prim算法的时间复杂度为O(n^2)与边数无关适于稠密图。 ·Kruskal算法的时间复杂度为O(lge),主要取决于边数,较适合于稀疏图。 最短路径的算法:·Dijkstra算法,时间复杂度为O(n^2)。·类似于prim算法。 拓扑排序:是将有向无环图G中所有顶点排成一个线性序列,若 ∈E(G),则在线性序列u在v之前,这种线性序列称为拓扑序列。 拓扑排序也有两种方法:·无前趋的顶点优先,每次输出一个无前趋的结点并删去此结点及其出边,最后得到的序列即拓扑序列。 ·无后继的结点优先:每次输出一个无后继的结点并删去此结点及其入边,最后得到的序列是逆拓扑序列。 第八章 排序 记录中可用某一项来标识一个记录,则称为关键字项,该数据项的值称为关键字。 排序是使文件中的记录按关键字递增(或递减)次序排列起来。 ·基本操作:比较关键字大小;改变指向记录的指针或移动记录。 ·存储结构:顺序结构、链表结构、索引结构。 经过排序后这些具有相同关键字的记录之间的相对次序保持不变,则称这种排序方法是稳定的,否则排序算法是不稳定的。 排序过程中不涉及数据的内、外存交换则称之为“内部排序”(内排序),反之,若存在数据的内外存交换,则称之为外排序。 内部排序方法可分五类:插入排序、选择排序、交换排序、归并排序和分配排序。 评价排序算法好坏的标准主要有两条:执行时间和所需的辅助空间,另外算法的复杂程序也是要考虑的一个因素。 插入排序:·直接插入排序: ·逐个向前插入到合适位置。 ·哨兵(监视哨)有两个作用: ·作为临变量存放R[i] ·是在查找循环中用来监视下标变量j是否越界。 ·直接插入排序是就地的稳定排序。时间复杂度为O(n^2),比较次数为(n+2)(n-1)/2;移动次数为(n+4)(n-1)/2; ·希尔排序: ·等间隔的数据比较并按要求顺序排列,最后间隔为1. ·希尔排序是就地的不稳定排序。时间复杂度为O(n^1.25),比较次数为(n^1.25);移动次数为(1.6n^1.25); 交换排序:·冒泡排序:·自下向上确定最轻的一个。·自上向下确定最重的一个。·自下向上确定最轻的一个,后自上向下确定最重的一个。 ·冒泡排序是就地的稳定排序。时间复杂度为O(n^2),比较次数为n(n-1)/2;移动次数为3n(n-1)/2; ·快速排序:·以第一个元素为参考基准,设定、动两个指针,发生交换后指针交换位置,直到指针重合。重复直到排序完成。 ·快速排序是非就地的不稳定排序。时间复杂度为O(nlog2n),比较次数为n(n-1)/2; 选择排序:·直接选择排序: ·选择最小的放在比较区前。 ·直接选择排序就地的不稳定排序。时间复杂度为O(n^2)。比较次数为n(n-1)/2; ·堆排序 ·建堆:按层次将数据填入完全二叉树,从int(n/2)处向前逐个调整位置。 ·然后将树根与最后一个叶子交换值并断开与树的连接并重建堆,直到全断开。 ·堆排序是就地不稳定的排序,时间复杂度为O(nlog2n),不适宜于记录数较少的文件。 归并排序: ·先两个一组排序,形成(n+1)/2组,再将两组并一组,直到剩下一组为止。 ·归并排序是非就地稳定排序,时间复杂度是O(nlog2n), 分配排序:·箱排序: ·按关键字的取值范围确定箱子数,按关键字投入箱子,链接所有非空箱。 ·箱排序的平均时间复杂度是线性的O(n)。 ·基数排序:·从低位到高位依次对关键字进行箱排序。 ·基数排序是非就稳定的排序,时间复杂度是O(d*n+d*rd)。 各种排序方法的比较和选择: ·。待排序的记录数目n;n较大的要用时间复杂度为O(nlog2n)的排序方法; ·记录的大小(规模);记录大用链表作为存储结构,而快速排序和堆排序在链表上难于实现; ·关键字的结构及其初始状态; ·对稳定性的要求; ·语言工具的条件; ·存储结构; ·时间和辅助空间复杂度。 第九章 查找 查找的同时对表做修改操作(如插入或删除)则相应的表称之为动态查找表,否则称之为静态查找表。 衡量查找算法效率优劣的标准是在查找过程中对关键字需要执行的平均比较次数(即平均查找长度ASL)。 线性表查找的方法: ·顺序查找:逐个查找,ASL=(n+1)/2; ·二分查找:取中点int(n/2)比较,若小就比左区间,大就比右区间。用二叉判定树表示。ASL=(∑(每层结点数*层数))/N. ·分块查找。要求“分块有序”,将表分成若干块内部不一定有序,并抽取各块中的关键字及其位置建立有序索引表。 二叉排序树(BST)定义是:二叉排序树是空树或者满足如下性质的二叉树: ·若它的左子树非空,则左子树上所有结点的值均小于根结点的值; ·若它的右子树非空,则右子树上所有结点的值均大于根结点的值; ·左、右子树本身又是一棵二叉排序树。 二叉排序树的插入、建立、删除的算法平均时间性能是O(nlog2n)。 二叉排序树的删除操作可分三种情况进行处理: ·*P是叶子,则直接删除*P,即将*P的双亲*parent中指向*P的指针域置空即可。 ·*P只有一个孩子*child,此时只需将*child和*p的双亲直接连接就可删去*p. ·*p有两个孩子,则先将*p结点的中序后继结点的数据到*p,删除中序后继结点。 关于B-树(多路平衡查找树)。它适合在磁盘等直接存取设备上组织动态的查找表,是一种外查找算法。建立的方式是从下向上拱起。 散列技术:将结点按其关键字的散列地址存储到散列表的过程称为散列。散列函数的选择有两条标准:简单和均匀。 常见的散列函数构的造方法: ·。平方取中法:hash=int((x^2)%100) ·。除余法:表长为m,hash=x%m ·。相乘取整法:hash=int(m*(x*A-int(x*A));A=0.618 ·。随机数法:hash=random(x)。 处理冲突的方法:·开放定址法: ·一般形式为hi=(h(key)+di)%m1≤i≤m-1,开放定址法要求散列表的装填因子α≤1. ·开放定址法类型: ·线性探查法:address=(hash(x)+i)%m; ·二次探查法:address=(hash(x)+i^2)%m; ·双重散列法:address=(hash(x)+i*hash(y))%m; ·拉链法: ·是将所有关键字为同义词的结点链接在同一个单链表中。 ·拉链法的优点: ·拉链法处理冲突简单,且无堆积现象; ·链表上的结点空间是动态申请的适于无法确定表长的情况; ·拉链法中α可以大于1,结点较大时其指针域可忽略,因此节省空间; ·拉链法构造的散列表删除结点易实现。 ·拉链法也有缺点:当结点规模较小时,用拉链法中的指针域也要占用额外空间,还是开放定址法省空间。 第十章 文件 文件是性质相同的记录的集合。记录是文件中存取的基本单位,数据项是文件可使用的最小单位,数据项有时称字段或者属性。 文件 ·逻辑结构是一种线性结构。 ·操作有:检索和维护。并有实时和批量处理两种处理方式。 文件 ·存储结构是指文件在外存上的组织方式。 ·基本的组织方式有:顺序组织、索引组织、散列组织和链组织。 ·常用的文件组织方式:顺序文件、索引文件、散列文件和多关键字文件。 评价一个文件组织的效率,是执行文件操作所花费的时间和文件组织所需的存储空间。 检索功能的多寡和速度的快慢,是衡量文件操作质量的重要标志。 顺序文件是指按记录进入文件的先后顺序存放、其逻辑顺序和物理顺序一致的文件。主关键字有序称顺序有序文件,否则称顺序无序文件。 一切存储在顺序存储器(如磁带)上的文件都只能顺序文件,只能按顺序查找法存取。 顺序文件的插入、删除和修改只能通过复制整个文件实现。 索引文件的组织方式:通常是在主文件之外建立一张索引表指明逻辑记录和物理记录之间一一对应的关系,它和主文件一起构成索引文件。 索引非顺序文件中的索引表为稠密索引。索引顺序文件中的索引表为稀疏索引。 若记录很大使得索引表也很大时,可对索引表再建立索引,称为查找表。是一种静态索引。 索引顺序文件常用的有两种: ·ISAM索引顺序存取方法:是专为磁盘存取文件设计的,采用静态索引结构。 ·VSAM虚拟存储存取方法:采用B+树作为动态索引结构,由索引集、顺序集、数据集组成。 散列文件是利用散列存储方式组织的文件,亦称为直接存取文件。 散列文件 ·优点是:文件随机存放,记录不需要排序;插入删除方便;存取速度快;不需要索引区,节省存储空间。 ·缺点是:不能进行顺序存取,只能按关键字随机存取,且询问方式限地简单询问,需要重新组织文件。 多重表文件:对需要查询的次关键字建立相应的索引,对相同次关键字的记录建一个链表并将链表头指针、长度、次关键字作为索引表的索引项。 倒排表:次关键字索引表称倒排表,主文件和倒排表构成倒排文件。2023-11-20 05:08:471
哈希函数的三个特性
哈希函数的三个特性是任何对象作为哈希函数的输入都可以得到一个相应的哈希值;两个相同的对象作为哈希函数的输入,它们总会得到一样的哈希值;两个不同的对象作为哈希函数的输入,它们不一定会得到不同的哈希值。一般的线性表,树中,记录在结构中的相对位置是随机的,即和记录的关键字之间不存在确定的关系,因此,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在“比较“的基础上,查找的效率依赖于查找过程中所进行的比较次数。理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。哈希表中元素是由哈希函数确定的。将数据元素的关键字K作为自变量,通过一定的函数关系,计算出的值,即为该元素的存储地址。在哈希表中,不同的关键字值对应到同一个存储位置的现象。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址。哈希函数冲突的处理及解决方法:冲突:在哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)=H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址。解决冲突的方法:1、链接法(拉链法)。将具有同一散列地址的记录存储在一条线性链表中。例,除留余数法中,设关键字为(18,14,01,68,27,55,79),除数为13。散列地址为(5,1,1,3,1,3,1)。2、开放定址法。如果h(k)已经被占用,按如下序列探查:(h(k)+p⑴)%TSize,(h(k)+p⑵)%TSize,…,h(k)+p(i))%TSize。其中,h(k)为哈希函数,TSize为哈希表长,p(i)为探查函数。在h(k)+p(i-1))%TSize的基础上,若发现冲突,则使用增量p(i)进行新的探测,直至无冲突出现为止。其中,根据探查函数p(i)的不同,开放定址法又分为线性探查法(p(i)=i:1,2,3,…)。2023-11-20 05:08:541
线性探测再散列法是什么?
线性探测再散列也称杂凑技术。是一种较快的查找技术。线性探测再散列是哈希表解决冲突的一种计算方法,Hi=(H(key)+di)%m,i=1,2,……k(k<=m-1),H(key)哈希函数,m哈希表长,di增量序列当,di值可能为1,2,3,...m-1,称线性探测再散列,用该方法处理冲突的方法:开放寻址法、再散列法和链地址法(拉链法)。解决冲突的方法一般有线性探测再散列法、随机探测法、再哈希法、链地址法等,其中线性再散列法较简单,其计算公式为:Hi=(H(K)+di)MOD p式中di=1,2,…常用的哈希函数1.直接定址法。仅适合于:地址集合的大小 == 关键字集合的大小。2.数字分析法。对关键字进行分析,取关键字的若干位或其组合作哈希地址。仅适合于:能预先估计出全体关键字的每一位上各种数字出现的频度。3.平方取中法。以关键字的平方值的中间几位作为存储地址。4.折叠法。将关键字分割成位数相同的几部分,然后取这几部分的叠加和(舍去进位)做哈希地址。移位叠加/间界叠加。适合于: 关键字的数字位数特别多,且每一位上数字分布大致均匀情况。5.除留余数法。取关键字被某个不大于哈希表表长m的数p除后所得余数作哈希地址,即H(key)=key%p,p<=m。6.随机数法。取关键字的伪随机函数值作哈希地址,即H(key)=random(key),适于关键字长度不等的情况。以上内容参考:线性探测再散列-学术百科-知网空间2023-11-20 05:09:401
算法导论第11章散列表线性探查法群集现象中,当一个空槽前有i个满的槽时,该空槽为下一个被占用槽的概率
是这样的,如果一个空槽前有i个满的槽,则如果哈希到这i个槽中的任何一个,用线性探测法,最终都会使用这个空槽,就有i中情况,再加上正好哈希到这个空槽的情况,一共是i+1中情况。2023-11-20 05:09:522
线性探测再散列法是啥?
线性探测再散列法是计算机程序解决散列表冲突时所采取的一种策略。散列表这种数据结构用于保存键值对,并且能通过给出的键来查找表中对应的值。 与二次探测和双散列一样,线性探测是一种开放寻址的策略。在这些策略里,散列表的每个单元都存储一对键值对。 当散列函数对一个给定值产生一个键,并且这个键指向散列表中某个已经被另一个键值对所占用的单元时,线性探测用于解决此时产生的冲突。2023-11-20 05:09:591
散列表的地址空间为0-16,h(k)=k mod 17,用线性探查法解决碰撞问题,从空散列表开始插入关键码值190,
190 % 17 = 389 % 17 = 4217 % 17 = 13208 % 17 = 1475 % 17 = 7177 % 17 = 7177 插入哈希表时地址冲突,根据线性探查法,地址往后延一个,就是82023-11-20 05:10:071
线性探测再散列法是什么?
当di值可能为1,2,3,...m-1,称线性探测再散列。具体如下:开放地址法有一个公式:Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)。其中,m为哈希表的表长。di是产生冲突的时候的增量序列。如果di值可能为1,2,3,...m-1,称线性探测再散列。如果di取1,则每次冲突之后,向后移动1个位置。如果di取值可能为1,-1,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2),称二次探测再散列,如果di取值可能为伪随机数列。称伪随机探测再散列。处理冲突的方法:开放寻址法:Hi=(H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:1、di=1,2,3,…, m-1,称线性探测再散列;2、di=1^2, -1^2, 2^2,-2^2, 3^2, …, ±(k)^2,(k<=m/2)称二次探测再散列。3、di=伪随机数序列,称伪随机探测再散列。再散列法:Hi=RHi(key), i=1,2,…,k. RHi均是不同的散列函数,即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,这种方法不易产生“聚集”,但增加了计算时间。链地址法(拉链法):将所有关键字为同义词的记录存储在同一线性链表中。用二次探测再散列法解决冲突:1、(key+1^2)%11=(49+1)%11=6,仍然发生冲突。2、(key-1^2)%11=(49-1)%11=4,仍然发生冲突。3、(key+2^2)%11=(49+4)%11=9,不再发生冲突。以上内容参考百度百科-哈希表2023-11-20 05:10:161
哈希函数是什么
哈希表中元素是由哈希函数确定的。将数据元素的关键字K作为自变量,通过一定的函数关系(称为哈希函数),计算出的值,即为该元素的存储地址。表示为:Addr = H(key)为此在建立一个哈希表之前需要解决两个主要问题:⑴构造一个合适的哈希函数均匀性 H(key)的值均匀分布在哈希表中;简单 以提高地址计算的速度⑵冲突的处理冲突:在哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)= H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址。解决冲突的方法:[1] ⑴链接法(拉链法)。将具有同一散列地址的记录存储在一条线性链表中。例,除留余数法中,设关键字为 (18,14,01,68,27,55,79),除数为13。散列地址为 (5,1,1,3,1,3,1),哈希散列表如图。⑵开放定址法。如果h(k)已经被占用,按如下序列探查:(h(k)+p⑴)%TSize,(h(k)+p⑵)%TSize,…,(h(k)+p(i))%TSize,…其中,h(k)为哈希函数,TSize为哈希表长,p(i)为探查函数。在 h(k)+p(i-1))%TSize的基础上,若发现冲突,则使用增量 p(i) 进行新的探测,直至无冲突出现为止。其中,根据探查函数p(i)的不同,开放定址法又分为线性探查法(p(i) = i : 1,2,3,…),二次探查法(p(i)=(-1)^(i-1)*((i+1)/2)^2,探查序列依次为:1, -1,4, -4, 9 …),随机探查法(p(i): 随机数),双散列函数法(双散列函数h(key) ,hp (key)若h(key)出现冲突,则再使用hp (key)求取散列地址。探查序列为:h(k),h(k)+ hp(k),…,h(k)+ i*hp(k))。⑶桶定址法。桶:一片足够大的存储空间。桶定址:为表中的每个地址关联一个桶。如果桶已经满了,可以使用开放定址法来处理。例如,插入A5,A2,A3,B5,A9,B2,B9,C2,采用线性探查法解决冲突。望采纳,谢谢2023-11-20 05:10:291
查找 - 散列技术 - 散列表上的运算
散列表上的运算 散列表上的运算有查找 插入和删除 其中主要是查找 这是因为散列表的目的主要是用于快速查找 且插入和删除均要用到查 找操作 散列表类型说明 #define NIL //空结点标记依赖于关键字类型 本节假定关键字均为非负整数 #define M //表长度依赖于应用 但一般应根据 确定m为一素数 typedef struct{ //散列表结点类型 KeyType key; InfoType otherinfo; //此类依赖于应用 }NodeType; typedef NodeType HashTable[m]; //散列表类型 基于开放地址法的查找算法 散列表的查找过程和建表过程相似 假设给定的值为K 根据建表时设定的散列函数h 计算出散列地址h(K) 若表中该地址单元 为空 则查找失败;否则将该地址中的结点与给定值K比较 若相等则查找成功 否则按建表时设定的处理冲突的方法找下一个地址 如此反复下去 直到某个地址单元为空(查找失败)或者关键字比较相等(查找成功)为止 ( )开放地址法一般形式的函数表示 int Hash(KeyType k int i) { //求在散列表T[ m ]中第i次探查的散列地址hi ≤i≤m //下面的h是散列函数 Increment是求增量序列的函数 它依赖于解决冲突的方法 return(h(K)+Increment(i))%m; //Increment(i)相当于是d i } 若散列函数用除余法构造 并假设使用线性探查的开放定址法处理冲突 则上述函数中的h(K)和Increment(i)可定义为 int h(KeyType K){ //用除余法求K的散列地址 return K%m; } int Increment(int i){//用线性探查法求第i个增量d i return i; //若用二次探查法 则返回i*i } ( )通用的开放定址法的散列表查找算法 int HashSearch(HashTable T KeyType K int *pos) { //在散列表T[ m ]中查找K 成功时返回 失败有两种情况 找到一个开放地址 //时返回 表满未找到时返回 *pos记录找到K或找到空结点时表中的位置 int i= ; //记录探查次数 do{ *pos=Hash(K i); //求探查地址hi if(T[*pos] key==K) return l; //查找成功返回 if(T[*pos] key==NIL) return ;//查找到空结点返回 }while(++i <m) 最多做m次探查 return -1; //表满且未找到时,查找失败 } //HashSearch 注意: 上述算法适用于任何开放定址法,只要给出函数Hash中的散列函数h(K)和增量函数Increment(i)即可。Tw.wiNGWit.Com但要提高查找效率时, 可将确定的散列函数和求增量的方法直接写入算法HashSearch中,相应的算法【参见习题】。 3、基于开放地址法的插入及建表 建表时首先要将表中各结点的关键字清空,使其地址为开放的;然后调用插入算法将给定的关键字序列依次插入表中。 插入算法首先调用查找算法,若在表中找到待插入的关键字或表已满,则插入失败;若在表中找到一个开放地址,则将待插入的 结点插入其中,即插入成功。 void Hashlnsert(HashTable T,NodeTypene w) { //将新结点new插入散列表T[0..m-1]中 int pos,sign; sign=HashSearch(T,new.key,&pos); //在表T中查找new的插入位置 if(!sign) //找到一个开放的地址pos T[pos]=new; //插入新结点new,插入成功 else //插人失败 if(sign>0) printf("duplicate key!"); //重复的关键字 else //sign<0 Error("hashtableoverflow!"); //表满错误,终止程序执行 } //Hashlnsert void CreateHashTable(HashTable T,NodeType A[],int n) { //根据A[0..n-1]中结点建立散列表T[0..m-1] int i if(n>m) //用开放定址法处理冲突时,装填因子α须不大于1 Error("Load factor>1"); for(i=0;i <m;i++) p=""> </m;i++)> T[i].key=NIL; //将各关键字清空,使地址i为开放地址 for(i=0;i <n;i++) 依次将a[0..n-1]插入到散列表t[0..m-1]中 Hashlnsert(T,A[i]); } //CreateHashTable 4、删除 基于开放定址法的散列表不宜执行散列表的删除操作。若必须在散列表中删除结点,则不能将被删结点的关键字置为NIL,而应该 将其置为特定的标记DELETED。 因此须对查找操作做相应的修改,使之探查到此标记时继续探查下去。同时也要修改插人操作,使其探查到DELETED标记时,将 相应的表单元视为一个空单元,将新结点插入其中。这样做无疑增加了时间开销,并且查找时间不再依赖于装填因子。 因此,当必须对散列表做删除结点的操作时,一般是用拉链法来解决冲突。 注意: 用拉链法处理冲突时的有关散列表上的算法【参见练习】。 5、性能分析 插入和删除的时间均取决于查找,故下面只分析查找操作的时间性能。 虽然散列表在关键字和存储位置之间建立了对应关系,理想情况是无须关键字的比较就可找到待查关键字。但是由于冲突的存在 ,散列表的查找过程仍是一个和关键字比较的过程,不过散列表的平均查找长度比顺序查找、二分查找等完全依赖于关键字比较的查 找要小得多。 (1)查找成功的ASL 散列表上的查找优于顺序查找和二分查找。 【例】在例9.1和例9.2的散列表中,在结点的查找概率相等的假设下,线性探查法和拉链法查找成功的平均查找长度分别为: ASL=(1×6+2×2+3×l+9×1)/10=2.2 //线性探查法 ASL=(1×7+2×2+3×1)/10=1.4 //拉链法 而当n=10时,顺序查找和二分查找的平均查找长度(成功时)分别为: ASL=(10+1)/2=5.5 //顺序查找 ASL=(1×l+2×2+3×4+4×3)/10=2.9 //二分查找,可由判定树求出该值 (2) 查找不成功的ASL 对于不成功的查找,顺序查找和二分查找所需进行的关键字比较次数仅取决于表长,而散列查找所需进行的关键字比较次数和待 查结点有关。因此,在等概率情况下,也可将散列表在查找不成功时的平均查找长度,定义为查找不成功时对关键字需要执行的平均 比较次数。 【例】例9.1和例9.2的散列表中,在等概率情况下,查找不成功时的线性探查法和拉链法的平均查找长度分别为: ASL unsucc =(9+8+7+6+5+4+3+2+1+1+2+1+10)/13=59/13≈4.54 ASL unsucc =(1+0+2+1+0+1+1+0+0+0+1+0+3)/13≈10/13≈0.77 注意: ①由同一个散列函数、不同的解决冲突方法构造的散列表,其平均查找长度是不相同的。 ②散列表的平均查找长度不是结点个数n的函数,而是装填因子α的函数。因此在设计散列表时可选择α以控制散列表的平均查找 长度。 ③ α的取值 α越小,产生冲突的机会就小,但α过小,空间的浪费就过多。只要α选择合适,散列表上的平均查找长度就是一个常数,即散 列表上查找的平均时间为O(1)。 ④ 散列法与其他查找方法的区别 除散列法外,其他查找方法有共同特征为:均是建立在比较关键字的基础上。其中顺序查找是对无序集合的查找,每次关键字的比较 结果为"="或"!="两种可能,其平均时间为O(n);其余的查找均是对有序集合的查找,每次关键字的比较有"="、"<"和">"三种可能 ,且每次比较后均能缩小下次的查找范围,故查找速度更快,其平均时间为O(lgn)。而散列法是根据关键字直接求出地址的查找方法 ,其查找的期望时间为O(1)。 lishixinzhi/Article/program/sjjg/201311/236752023-11-20 05:10:451
求数据结构试题…重点
这是我们老师要求的重点,即考点。打印出来,背一下就行了,准过!第一章:绪论1.1:数据结构课程的任务是:讨论数据的各种逻辑结构、在计算机中的存储结构以及各种操作的算法设计。1.2:数据:是客观描述事物的数字、字符以及所有的能输入到计算机中并能被计算机接收的各种集合的统称。数据元素:表示一个事物的一组数据称作是一个数据元素,是数据的基本单位。数据项:是数据元素中有独立含义的、不可分割的最小标识单位。数据结构概念包含三个方面:数据的逻辑结构、数据的存储结构的数据的操作。1.3数据的逻辑结构指数据元素之间的逻辑关系,用一个数据元素的集合定义在此集合上的若干关系来表示,数据结构可以分为三种:线性结构、树结构和图。1.4:数据元素及其关系在计算机中的存储表示称为数据的存储结构,也称为物理结构。 数据的存储结构基本形式有两种:顺序存储结构和链式存储结构。 2.1:算法:一个算法是一个有穷规则的集合,其规则确定一个解决某一特定类型问题的操作序列。算法规则需满足以下五个特性:输入——算法有零个或多个输入数据。 输出——算法有一个或多个输出数据,与输入数据有某种特定关系。 有穷性——算法必须在执行又穷步之后结束。 确定性——算法的每个步骤必须含义明确,无二义性。 可行性——算法的每步操作必须是基本的,它们的原则上都能够精确地进行,用笔和纸做有穷次就可以完成。 有穷性和可行性是算法最重要的两个特征。2.2:算法与数据结构:算法建立数据结构之上,对数据结构的操作需用算法来描述。 算法设计依赖数据的逻辑结构,算法实现依赖数据结构的存储结构。2.3:算法的设计应满足五个目标:正确性:算法应确切的满足应用问题的需求,这是算法设计的基本目标。 健壮性:即使输入数据不合适,算法也能做出适当的处理,不会导致不可控结 高时间效率:算法的执行时间越短,时间效率越高。 果。 高空间效率:算法执行时占用的存储空间越少,空间效率越高。 可读性:算法的可读性有利于人们对算法的理解。 2.4:度量算法的时间效率,时间复杂度,(课本39页)。2.5:递归定义:即用一个概念本身直接或间接地定义它自己。递归定义有两个条件:至少有一条初始定义是非递归的,如1!=1. 由已知函数值逐步递推计算出未知函数值,如用(n-1)!定义n!。 第二章:线性表1.1线性表:线性表是由n(n>=0)个类型相同的数据元素a0,a1,a2,…an-1,组成的有限序列,记作: LinearList = (a0,a1,a2,…an-1)其中,元素ai可以是整数、浮点数、字符、也可以是对象。n是线性表的元素个数,成为线性表长度。若n=0,则LinearList为空表。若n>0,则a0没有前驱元素,an-1没有后继元素,ai(0<i<n-1)有且仅有一个直接前驱元素ai-1和一个直接后继元素ai+1。1.2线性表的顺序存储是用一组连续的内存单元依次存放线性表的数据元素,元素在内存的物理存储次序与它们在线性表中的逻辑次序相同。线性表的数据元素数据同一种数据类型,设每个元素占用c字节,a0的存储地址为Loc(a0),则ai的存储地址Loc(ai)为:Loc(ai) = Loc(a0)+ i*c 数组是顺序存储的随机存储结构,它占用一组连续的存储单元,通过下标识别元素,元素地址是下标的线性函数。1.3:顺序表的插入和删除操作要移动数据元素。平均移动次数是 属数据表长度的一半。(课本第50页)1.4:线性表的链式存储是用若干地址分散的存储单元存储数据元素,逻辑上相邻的数据元素在物理位置上不一定相邻,必须采用附加信息表示数据元素之间的顺序关系。它有两个域组成:数据域和地址域。通常成为节点。(课本第55页及56页)1.5单链表(课本56页)单链表的遍历:Node<E> p = head; while(p!=null){ 访问p节点;p = p.next;}单链表的插入和删除操作非常简便,只要改变节点间的链接关系,不需移动数据元素。单链表的插入操作:1):空表插入/头插入 2)中间插入/尾插入 if(head == null) Node<E> q = new Node<E>(x); { head = new Node<E>(x); q.next = p.next; }else{ p.next = q; Node<E> q=new Node<E>(x); 中间插入或尾插入都不会改变单表 q.next = head; 的头指针head。 head = q; }单链表的删除操作:头删除:head = head.next; 中间/尾删除:if(p.next!=null){ p.next = p.next.next;} 循环单链表:如果单链表最后一个节点的next链保存单链表的头指针head值,则该单链表成为环形结构,称为循环单链表。(课本67)若rear是单链表的尾指针,则执行(rear.next=head;)语句,使单链表成为一条循环单链表。当head.next==head时,循环单链表为空。1.6:双链表结构:双链表的每个结点有两个链域,分别指向它的前驱和后继结点, 当head.next==null时,双链表为空。 设p指向双链表中非两端的某个结点,则成立下列关系:p=p.next.prev=p.prev.next。双链表的插入和删除:1)插入 2)删除q=new DLinkNode(x); p.prev.next = p.next;q.prev=p.prev;q.next =p; if(p.next=null){p.prev.next = q;p.prev=q; (p.next).prev = p.prev;}循环双链表:当head.next==head且head.prev==head时,循环双链表为空。第三章:栈和队列1.1栈:栈是一种特殊的线性表,其中插入和删除操作只允许在线性表的一端进行。允许操作的一端称为栈顶,不允许操作的一端称为栈底。栈有顺序栈和链式栈。栈中插入元素的操作称为入栈,删除元素的操作称为出栈。没有元素的中称为空栈。栈的进出栈顺序:后进先出,先进后出。(及75页的思考题)。1.2:队列:队列是一种特殊的线性表,其中插入和删除操作分别在线性表的两端进行。向队列中插入元素的过程称为入队,删除元素的过程称为出对,允许入队的一端称为队尾,允许出队的一端称为对头。没有元素的队列称为空队列。队列是先进先出。第四章:串1.1:串是一种特殊的线性表,其特殊性在于线性表中的每个元素是一个字符。一个串记为: s=“s0s1s2…sn-1” 其中n>=0,s是串名,一对双引号括起来的字符序列s0s1s2…sn-1是串值,si(i=0,1,2,…n-1)为特定字符集合中的一个字符。一个串中包含的字符个数称为串的长度。长度为0的串称为空串,记作“”,而由一个或多个空格字符构成的字符串称为空格串。子串:由串s中任意连续字符组成的一个子序列sub称为s的子串,s称为sub的主串。子串的序号是指该子串的第一个字符在主串中的序号。串比较:两个串可比较是否相等,也可比较大小。两个串(子串)相等的充要条件是两个串(子串)的长度相同,并且各对应位置上的字符也相同。两个串的大小由对应位置的第一个不同字符的大小决定,字符比较次序是从头开始依次向后。当两个串长度不等而对应位置的字符都相同时,较长的串定义为较“大”。第五章:数组和广义表1.1:数组是一种数据结构,数据元素具有相同的数据类型。一维数组的逻辑结构是线性表,多维数组是线性表的扩展。1.2:一维数组:一维数组采用顺序存储结构。一个一维数组占用一组连续的存储单元。设数组第一个元素a0的存储地址为Loc(a0),每个元素占用c字节,则数组其他元素ai的存储地址Loc(ai)为: Loc(ai)= Loc(a0)+i*c数组通过下标识别元素,元素地址是下标的线性函数。一个下标能够唯一确定一个元素,所划给的时间是O(1)。因此数组是随机存取结构,这是数组最大的优点。1.3:多维数组的遍历:有两种次序:行主序和列主序。行主序:以行为主序,按行递增访问数组元素,访问完第i行的所有元素之后再访问第i+1行的元素,同一行上按列递增访问数组元素。 a00,a01,…a0(n-1), a10,a11,…a1(n-1),…a(m-1)0,a(m-1)1,…,a(m-1)(n-1) 2)列主序:以列为主序,按列递增访问数组元素,访问完第j列的所有元素之后再访问第j+1列的元素,同一列上按列递增访问数组元素。 多维数组的存储结构:多维数组也是由多个一维数组组合而成,组合方式有一下两种。静态多维数组的顺序存储结构:可按行主序和列主序进行顺序存储。 按行主序存储时,元素aij的地址为:Loc(aij)= Loc(a00)+(i*n+j)*c按列主序存储时,Loc(aij)= Loc(a00)+(j*m+i)*c动态多维数组的存储结构。 二维数组元素地址就是两个下标的线性函数。无论采用哪种存储结构,多维数组都是基于一维数组的,因此也只能进行赋值、取值两种存取操作,不能进行插入,删除操作。第六章:树是数据元素(结点)之间具有层次关系的非线性结构。在树结构中,除根以外的结点只有一个直接前驱结点,可以有零至多个直接后继结点。根没有前驱结点。树是由n(n>=0)个结点组成的有限集合(树中元素通常称为结点)。N=0的树称为空树;n>0大的树T;@有一个特殊的结点称为根结点,它只有后继结点,没有前驱结点。@除根结点之外的其他结点分为m(m>=0)个互不相交的集合T0,T1,T3……..,Tm-1,其中每个集合Ti(0<=i<m)本身又是一棵树,称为根的子树。树是递归定义的。结点是树大的基本单位,若干个结点组成一棵子树,若干棵互不相交的子树组成一棵树。树的每个结点都是该树中某一棵子树的根。因此,树是由结点组成的、结点之间具有层次关系大的非线性结构。 结点的前驱结点称为其父母结点,反之,结点大的后继结点称为其孩子结点。一棵树中,只有根结点没有父母结点,其他结点有且仅有一个父母结点。拥有同一个父母结点的多个结点之间称为兄弟结点。结点的祖先是指从根结点到其父母结点所经过大的所有结点。结点的后代是指该结点的所有孩子结点,以及孩子的孩子等。结点的度是结点所拥有子树的棵数。度为0的结点称为叶子结点,又叫终端结点;树中除叶子结点之外的其他结点称为分支结点,又叫非叶子结点或非终端结点。树的度是指树中各结点度的最大值。结点的层次属性反应结点处于树中的层次位置。约定根结点的层次为1,其他结点的层次是其父母结点的层次加1。显然,兄弟结点的层次相同。树的高度或深度是树中结点的最大层次树。设树中x结点是y结点的父母结点,有序对(x,y)称为连接这两个结点的分支,也称为边。设(X0,X1,….,Xk-1)是由树中结点组成的一个序列,且(Xi,Xi+1)(0<=i<k-1)都是树中的边,则该序列称为从X0到Xk-1的一条路径。路径长度为路径上的边数。在树的定义中,结点的子树T0,T1…..,Tm-1之间没有次序,可以交换位置,称为无序树,简称树。如果结点的子树T0,T1……,Tm-1从左到右是有次序的,不能交换位置,则 称该树为有序树。森林是m(m>=0)棵互不相干的树的集合。给森林加上一个根结点就变成一棵树,将树的根节点删除就变成森林。二叉树的性质1:若根结点的层次为1,则二叉树第i层最多有2 的i-1次方(i>=1)个结点。二叉树的性质2:在高度为k的二叉树中,最多有2的k次方减一个结点。二叉树的性质3:设一棵二叉树的叶子结点数为n0,2度结点数为n2,则n0=n2+1。一棵高度为k的满二叉树是具有2的k次方减一个结点的二叉树。满二叉树中每一层的结点数目都达到最大值。对满二叉树的结点进行连续编号,约定根节点的序号为0,从根节点开始,自上而下,每层自左至右编号。一棵具有n个结点高度为k的二叉树,如果他的每个节点都与高度为k的满二叉树中序号为0~n-1的结点一一对应,则这棵二叉树为为完全二叉树。满二叉树是完全二叉树,而完全二叉树不一定是满二叉树。完全二叉树的第1~k-1层是满二叉树第k层不满,并且该层所有结点必须集中在该层左边的若干位置上。二叉树的性质4:一棵具有n个结点的完全二叉树,其高度k=log2n的绝对值+1二叉树的性质5:一棵具有n个结点的完全二叉树,对序号为i的结点,有@若i=0,则i为根节点,无父母结点;若i>0,则i的父母结点的序号为[(i-1)/2]。@若2i+1<n,则i的左孩子结点序号为2i+1;否则i无左孩子。@若2i+2<n,则i的右孩子结点的序号为2i+2,否则i无右孩子。二叉树的遍历二叉树的遍历是按照一定规则和次序访问二叉树中的所有结点,并且每个结点仅被访问一次。二叉树的三种次序遍历1:先根次序;访问根节点,遍历左子树,遍历右子树。2:中根次序;遍历左子树,访问右子树,遍历右子树。3:后根次序;遍历左子树,遍历右子树,访问根节点。先根次序遍历时,最先访问根节点;后根次序遍历时,最后访问根节点;中根次序遍历时,左子树上的结点在根节点之前访问,右子树上的结点在根节点之后访问。二叉树的插入和删除操作P147二叉树的层次遍历P149习题P167 6—10,6—19第七章图是由定点集合及顶点间的关系集合组成的一种数据关边系。顶点之间的关系成为边。一个图G记为G=(V,E),V是顶点A的有限集合,E是边的有限集合。即 V={A|A属于某个数据元素集合}E={(A,B)|A,B属于V}或E={<A,B>|A,B属于V且Path(A,B)}其中Path(A,B)表示从顶点A到B的一条单向通路,即Path(A,B)是有方向的。无向图中的边事没有方向,每条边用两个顶点的无序对表示。有向图中的边是有方向,每条边用两个顶点的有序对表示。完全图指图的边数达到最大值。n个顶点的完全图记为Kn。无向完全图Kn的边数为n*(n-1)/2,有向完全图Kn的边数为n*(n-1)。子图:设图G==(V,E),G"=(V",E"),若V"包含于V且E"包含于E,则称图G"是G的子图。若G"是G的真子图。连通图:在无向图G中,若从顶点VI到Vj有路径,则称Vi和Vj是联通的。若图G中任意一对顶点Vi和Vj(Vi不等于Vj)都是联通的,则称G为连通图。非连通图的极大联通子图称为该图的联通分量。强连通图:在有向图中,若在每一对顶点Vi和Vj(Vi不等于Vj)之间都存在一条从Vi到Vj的路径,也存在一条从Vi到Vj的路径,也存在一条从Vi到Vj的路径,则称该图的强连通图。非强连通图的极大强连通子图称为该图的强连通图分量。图的遍历遍历图是指从图G中任意一个顶点V出发,沿着图中的边前行,到达并访问图中的所有顶点,且每个顶点仅被访问一次。遍历图要考虑一下三个问题:@指定遍历的第一个访问顶点@由于一个顶点可能与多个顶点相邻,因此要在多个邻接顶点之间约定一种访问次序。@由于图中可能存在回路,在访问某个顶点之后,可能沿着某条路径又回到该顶点。深度优先搜索图的深度优先搜索策略是,访问某个顶点v,接着寻找v的另一个未被访问的邻接顶点w访问,如此反复执行,走过一条较长路径到达最远顶点;若顶点v没有未被访问的其他邻接顶点,则回到前一个被访问顶点,再寻找其他访问路径。图的深度优先搜索遍历算法P188 联通的无回路的无向图,简称树。树中的悬挂点又成为树叶,其他顶点称为分支点。各连通分量均为树的图称为森林,树是森林。由于树中无回路,因此树中必定无自身环也无重边(否则他有回路)若去掉树中的任意一条边,则变成森林,成为非联通图;若给树加上一条边,形成图中的一条回路,则不是树。P191生成树和生成森林:一个连通无向图的生成树是该图的一个极小联通生成子图,它包含原图中所有顶点(n个)以及足以构成一棵树的n-1条边。 一个非联通的无向图,其各连通图分量的生成图组成该图的生成森林。图的生成图或生成森林不是唯一的,从不同顶点开始、采用不同遍历可以得到不同的生成树或森林。 在生成树中,任何树中,任何两个顶点之间只有唯一的一条路径。第八章折半查找算法描述 P206,P207二叉排序树及其查找:二叉排序树或者是一棵空树;或者是具有下列性质的二叉树:@每个结点都有一个作为查找依据的关键字,所有结点的关键字互不相同。@若一个结点的左子树不空,则左子树上所有结点的关键字均小于这个节点的关键字;@每个结点的左右子树也分别为二叉排序树。在一棵二叉排序树中,查找值为value的结点,算法描述如下:@从根结点开始,设p指向根结点@将value与p结点的关键字进行比较,若两者相等,则查找成功;若value值较小,则在p的左子树中继续查找;若value值较大,则在p的右子树中继续查找。@重复执行上一步,直到查找成功或p为空,若p为空,则查找不成功。习题 8-6 第九章直接插入排序算法描述:p228冒泡排序算法的描述:p232快速排序算法描述p233直接选择排序算法描述p236直接选择排序算法实现如下:Public static void selectSort(int[]table){ for(int i=0;i<table.length-1;i++){ int min=I; for(int j=i+1;j<table.length;j++){ if(table[j]<table[min]) min=j; if(min!=i){ int temp=table[i]; table[i]==table[min]; table[min]=temp;}}}}堆排序是完全二叉树的应用,是充分利用完全二叉树特性的一种选择排序。堆定义:设n个元素的数据序列{k0,k1,。。。。kn-1},当且仅当满足下列关系k1<=k2i+1且ki<=k2i+2 i=0,1,2,3,….,[n/2-1]或ki>==k2i+1且ki>=2i+2i=0,1,2,3,…..[n/2-1]时,序列{k0,k1…….kn-1}称为最小堆或最大堆。将最小(大)堆看成是一颗完全二叉树的层次遍历序列,则任意一个结点的关键字都小于等于(大于等于)它的孩子节点的关键字值,由此可知,根结点值最小(大)。根据二叉树的性质5,完全二叉树中的第i(0<=i<n)个结点,如果有孩子,则左孩子为第2i+1个结点,右孩子为第2i+2个结点。希望对你会有所帮助。2023-11-20 05:11:042
C语言实现哈希表的相关运算算法 编写程序实现哈希表的构造过程。
#define MaxSize 100 //定义最大哈希表长度#define NULLKEY -1 //定义空关键字值#define DELKEY -2 //定义被删关键字值typedef int KeyType; //关键字类型typedef char * InfoType; //其他数据类型typedef struct{ KeyType key; //关键字域 InfoType data; //其他数据域 int count; //探查次数域} HashData;typedef HashData HashTable[MaxSize]; //哈希表类型void InsertHT(HashTable ha,int &n,KeyType k,int p) //将关键字k插入到哈希表中{ int i,adr; adr=k % p; if (ha[adr].key==NULLKEY || ha[adr].key==DELKEY) //x[j]可以直接放在哈希表中 { ha[adr].key=k; ha[adr].count=1; } else //发生冲突时采用线性探查法解决冲突 { i=1; //i记录x[j]发生冲突的次数 do { adr=(adr+1) % p; i++; } while (ha[adr].key!=NULLKEY && ha[adr].key!=DELKEY); ha[adr].key=k; ha[adr].count=i; } n++;}void CreateHT(HashTable ha,KeyType x[],int n,2023-11-20 05:11:131
线性表---解决冲突(c语言)
开放地址法 1.冲突处理方法一---开放地址法 当发生地址冲突后,求解下一个地址用: ND=(D+di)%m i=1,2,…,k(k<=m-1) 其中:m为哈希表长度,di为增量序列。增量序列的不同取法,又构成不同的开放地址法。 (1)线性探测再散列 D=H(key); ND=(D+di)%m; di取1,2,3,……,m-1 线性探测再散列处理冲突的基本思想:若数据元素在存储地址D发生冲突,则放到存储地址(D+1)%m;若又发生冲突则放到存储地址(D+2)%m;若再发生冲突则放到存储地址(D+3)%m;……;直到碰到第一个为空的存储地址(D+i)%m,则将数据元素存放在该存储空间。 (2)二次探测再散列 D=H(key); ND=(D+di)%m; di取1*1,-1*1,2*2,-2*2,……,K*K,-K*K(K≤m/2) (3)双散列法 首先使用第一个散列函数H1(key)及逆行那个散列,一旦发生冲突,则使用第二个函数H2(key)计算改项到达下一个存储地址的增量,其取值p和key有关,范围在1和m之间,并且与m互质的正整数。 D=H1(key); p=H2(key); ND=(D+p)%m; 值得提醒的是,对利用开放地址法查了冲突所产生的哈希表中删除一个元素,不能简单地直接删除,因为这样将截断其它具有相同哈希地址的元素的查找地址,所以应设定一个特殊的标志以表明该元素已被删除。不知道对你是否有用2023-11-20 05:11:223
散列的定义及常用方法
https://pan.baidu.com/share/init?surl=dF8XlFN 《大话数据结构》—— https://www.loneway.ren/book/20006 散列又称为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 冲突消解技术从实现上可分为内消解法和外消解法。 内消解的基本方法称为开地址法,其基本思想是插入数据并发现冲突是,设法在基本存储区为需要插入的数据另行安排一个位置。于是设计了一种叫计算位置安排方式—— 探查方式 。 常用的探查方式有 线性探查 和 双散列探查 。 1.线性探查: 2.双散列探查: 外消解法一半需要借助外部存储区间解决冲突,重用的方法有 溢出区法 和 桶散列法 。 当插入关键码的散列位置没有数据时就直接插入,发生冲突时将相应数据和关键码一起顺序存入溢出区。对应检索和删除也是先找散列位置,如果数据与关键码不匹配,则去溢出区顺序检索,直到找到或检索完。 散列表的每个元素只是一个引用域,饮用者一个保存实际数据的存储桶。拉链法中一个存储桶就是一个连表的头节点2023-11-20 05:11:291
对于线性表(7,34,55,25,64,46,20,10)进行散列存储时,若选用H(K)=K %9作为散列函数
答案选D,4个。分别是:55,64,46,10.H(K)=K%9,表示除以9的余数。由于地址重叠造成冲突,所以散列存储时,通常还要有解决冲突的办法,如线性探查法等等。2023-11-20 05:11:392
谁有数据结构的期末试题,借我参考下马上考试了
A:06-07第一学期期末考试试卷试卷代码:03266A 授课课时:112课程名称:数据结构与算法 适用对象:本科 一、单项选择题(从下列各题四个备选答案中选出一个正确答案,并将其代号写在答题纸相应位置处。答案错选或未选者,该题不得分。每小题2分,共24分。) 1.数据结构被形式地定义为(K,R),其中K是数据元素的有限集,R是K上的___有限集。 A.操作 B.映像 C.存储 D.关系 2.线性表若采用链式存储结构时,要求内存中可用存储单元的地址____。 A.必须连续的 B.部分地址必须连续的 C.一定是不续的 D.连续不连续都可以 3.一个栈的入栈序列是a、b、c、d、e,则栈的不可能输出序列是____。 A.edcba B.decba C.dceab D.abcde 4.一个队列的入队序列是1、2、3、4,则队列输出序列是____。 A.4、3、2、1 B.1、2、3、4 C.1、4、3、2 D.3、2、4、1 5.栈和队列的共同点是____。 A.都是先进后出 B.都是先进先出 C.只允许在端点处插入、删除元素 D.没有共同点 6.在一个单链表中,已知q所指结点是p所指结点的前驱结点,若在q和p之间插入s结点,则执行____。 A. s->next = p->next; p->next=s; B. p->next = s->next; s->next = p; C. q->next = s; s->next = p; D. p->next = s; s->next = q; 7.设串s1=‘ABCDEFG",s2=‘PQRST",函数con (x, y) 返回x与y串的连接串,函数subs (s, i, j) 返回串s的从序号i的字符开始的j个字符组成的子串,函数len (s) 返回串s的长度,则con (subs (s1, 2, len (s2)), subs (s1, len (s2), 2)) 的结果串是____。 A. BCDEF B. BCDEFG C. BCPQRST D. BCDEFEF 8.设高度为h的二叉树上只有度为0和度为2的结点,则此类二叉树中所包含的结点数至少为____。A. 2h B. 2h-1 C. 2h +1 D. h +1 9.某二叉树的前序遍历结点访问顺序是abdgcefh,中序遍历结点访问顺序是dgbaechf,则其后序遍历结点访问顺序是____。A. bdgcefha B. gdbecfha C. bdgaechf D. gdbehfca 10.具有6个顶点的无向图至少应有____条边才能确保是一个连通图。A. 5 B. 6 C. 7 D. 8 11.采用顺序查找方法查找长度为n的线性表时,每个元素的平均查找长度为–。A. n B. n/2 C. (n+1)/2 D. (n-1)/2 12.排序方法中,从未排序序列中挑选元素,并将其依次放入已排序序列(注:初始时为空)的一端的方法,称为____。A. 希尔排序 B. 归并排序 C. 插入排序 D. 选择排序 二、填空题(请在每小题的横线上填入正确内容,每空1分,共7分。) 1.在树形结构中,树根结点没有 结点,其余每个结点有且只有 个前驱结点。 2.对n个元素的序列进行起泡排序时,最少的比较次数是 。 3.空串是 ,其长度等于0。 4.一棵有n个结点的满二叉树共有 个叶子结点。 5.在散列函数H(key)=key % p中,p应取 。 6.已知模式串t=‘abcaabbabc", 其用KMP法求得的每个字符对应的next函数值为 。 三、简答题(本大题共3小题,每小题5分,共15分) 1.在对线性表的处理中一般使用两种存储结构,顺序存储结构和链式存储结构。试叙述在什么情况下使用顺序表比链表好? 2.简述什么是稳定的排序,什么是不稳定的排序。 3.下列中缀表达式对应的后缀形式是什么? (1) (A + B) * D + E / (F + A * D) + C (2) A && B|| ! (E > F) {注:按C的优先级) 四、判断题(本大题共10小题,命题正确的在题后括号内写 “T”,错误的在题后括号内写“F”,每小题1分,共10分) 1.数据元素不是数据的最小单位( )。 2.已知一棵二叉树的前序序列和后序序列可以唯一地构造出该二叉树。( ) 3.AOE网是一种带权的无环连通图。( ) 4.对于同一组待输入的关键码集合,虽然各关键码的输入次序不同,但得到的二叉搜索树都是相同的( )。 5.一棵树中的叶子数一定等于与其对应的二叉树的叶子数。( ) 6.邻接表只能用于有向图的存储,邻接矩阵对于有向图和无向图的存储都适用。( ) 7.折半插入排序是稳定的。( ) 8.在散列法中,使用双散列函数可保证绝对不产生冲突。( ) 9.消除递归不一定需要使用栈( ) 10.堆排序是交换排序的一种。( ) 五、分析应用题(本题共26分,1、4小题各6分,2、3小题各7分) 1.阅读后分析下面程序段的功能是什么? (6分) SeqStack S1, S2, tmp; DataType x; //设栈tmp和S2已做过初始化 while ( ! StackEmpty (S1)) { x=Pop(S1) ; Push(tmp,x); } while ( ! StackEmpty (tmp) ) { x=Pop(tmp); Push( S2, x); } 2.某子系统在通信联络中只可能出现8种字符,其出现的概率分别为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11试设计赫夫曼编码。(7分) 3.设散列表为HT[13], 散列函数为 H (key) = key %13。用线性探测再散列法解决冲突, 对下列关键码序列 12, 23, 45, 57, 20, 03, 78, 31, 15, 36 造表。画出相应的散列表, 并计算等概率下搜索成功的平均搜索长度。(7分) 4.设待排序的排序码序列为{12, 2, 16, 30, 28, 10, 16*, 20, 6, 18}, 试写出使用希尔排序(增量为5,2,1)方法每趟排序后的结果。(6分) 六、算法设计题(本题共18分,第1小题10分,第2小题8分) 1.编写一个算法frequency,统计在一个输入字符串中所含各个不同字符出现的频度。用适当的测试数据来验证这个算法。(10分) 2.在一棵以二叉链表表示的二叉树上,试写出用按层次顺序遍历二叉树的方法,并统计树中具有度为1的结点数目的算法。要求给出二叉链表的类型定义。(8分)答案:06-07第一学期期末考试参考答案与评分标准试卷代码:03266A 授课课时:112课程名称:数据结构与算法 适用对象:本科 一、单项选择题(每小题2分,共24分。) 1. D 2. D 3. C 4. B 5. C 6. C 7. D 8. B 9. D 10. A 11. C 12. D 二、填空题(每空1分,共7分。) 1.父(或前驱), 1 2. n-1 3. 不包含任何字符的串 4. (n+1)/2 5. 素数 6. 0111223123 三、简答题(每小题5分,共15分) 1.答:① 顺序存储时,相邻数据元素的存放地址也相邻(逻辑与物理统一);要求内存中可用存储单元的地址必须是连续的。优点:存储密度大,存储空间利用率高。缺点:插入或删除元素时不方便。②链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针优点:插入或删除元素时很方便,使用灵活。缺点:存储密度小(<1),存储空间利用率低。顺序表适宜于做查找这样的静态操作;链表宜于做插入、删除这样的动态操作。若线性表的长度变化不大,且其主要操作是查找,则采用顺序表;若线性表的长度变化较大,且其主要操作是插入、删除操作,则采用链表。 2.答:在排序序列中,任何两个相等的关键字Ki=Kj,如果在排序前的序列中Ki领先于Kj,若在排序后的序列中Ki仍领先于Kj,则称所用的排序方法是稳定的;反之,若可能使排序后的序列中Kj领先于Ki,则称所用的排序方法是不稳定的。 3.答:各中缀表达式的后缀形式如下: (1)AB+D*EFAD*+/+C+ (2)AB&&EF>!|| 四、判断题(本大题共10小题,命题正确的在题后括号内写 “T”,错误的在题后括号内写“F”,每小题1分,共10分) 1.T 2.F 3.T 4.F 5.F 6.F 7.T 8.F 9.T 10.F 五、分析应用题(1、4小题各6分,2、3小题各7分) 1.(6分) 答:程序段的功能是利用tmp栈将一个非空栈s1的所有元素按原样复制到一个栈s2当中去。 2.(7分) 答:为方便起见,设各种字符的权值w={5,29,7,8,14,23,3,11}。因为n=8,所以要构造的赫夫曼树共有m=2n-1=2*8-1=15个结点。生成的赫夫曼树为下图所示:赫夫曼编码为:概率为0.23的字符编码为:00 概率为0.11的字符编码为:010 概率为0.05的字符编码为:0110 概率为0.03的字符编码为:0111 概率为0.29的字符编码为:10 概率为0.14的字符编码为:110 概率为0.07的字符编码为:1110 概率为0.08的字符编码为:1111 3.(7分) 答:使用散列函数H(key)=key mod 13 有: H(12)=12, H(23)=10,H(45)=6,H(57)=5,H(20)=7,H(03)=3,H(78)=0,H(31)=5,H(15)=2,H(36)=10 利用线性探查法造表:0 1 2 3 4 5 6 7 8 9 10 11 1278 15 03 57 45 20 31 23 36 121 1 1 1 1 1 4 1 2 1 搜索成功的平均搜索长度为: ASL=1/10(1+1+1+1+1+1+4+1+2+1)=14/10 4.(6分) 答: 希尔排序(增量为5,2,1)六、算法设计题(第1小题10分,第2小题8分) 1. (10分) include <iostream.h> include”string.h” int charnumber=128; void frequency(string&s,int C[ ]){ for(int i=0;i< charnumber;i++) C[i]=0; for( i=0;i< s.length();i++) C[atoi(s[i])]++; for( i=0;i< charnumber;i++) if(C[i]>0) cout<<”(”<<i<<”): ”<<C[i]<<” ”; } 2. (8分) 类型定义(略) int Level(BiTree bt) //层次遍历二叉树,并统计度为1的结点的个数 { int num=0; //num统计度为1的结点的个数 if(bt){ QueueInit(Q); QueueIn(Q,bt);//Q是以二叉树结点指针为元素的队列 while(!QueueEmpty(Q)) { p=QueueOut(Q); printf(p->data); //出队,访问结点 if(p->lchild && !p->rchild ||!p->lchild && p->rchild) num++;//度为1的结点 if(p->lchild) QueueIn(Q,p->lchild); //非空左子女入队 if(p->rchild) QueueIn(Q,p->rchild); //非空右子女入队 } } return(num); //返回度为1的结点的个数 } B:06-07第一学期期末考试试卷试卷代码:03266B 授课课时:112课程名称:数据结构与算法 适用对象:本科 一、单项选择题(从下列各题四个备选答案中选出一个正确答案,并将其代号写在答题纸相应位置处。答案错选或未选者,该题不得分。每小题2分,共24分。) 1.数据结构被形式地定义为 (K, R),其中K是____的有限集,R是K上的关系有限集。 A.算法 B.数据元素 C.数据操作 D.逻辑结构 2.在数据结构中,从逻辑上可以把数据结构分成____。 A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 3.以下的叙述中,正确的是____。 A.线性表的存储结构优于链式存储结构 B.二维数组是其数据元素为线性表的线性表 C.栈的操作方式是先进先出 D.队列的操作方式是先进后出 4.若一个栈的入栈序列是1、2、3、… 、n,其输出序列为p1、p2、p3、… 、pn,若p1=n,则pi为____。 A. i B. n = i C. n - i +1 D.不确定 5.判断一个循环队列QU (最多元素为m) 为空的条件是____。 A. QU->front == QU->rear B. QU->front != QU->rear C. QU->front == (QU->rear+1)%m D. QU->front != (QU->rear+1)%m 6.在某单链表中,已知p所指结点不是最后结点,在p之后插入s所指结点,则执行____。 A. s->next = p; p->next=s; B. s->next = p->next; p->next = s; C. s->next = p->next; p = s; D. p->next = s; s->next = p; 7.串是一种特殊的线性表,其特殊性体现在____。 A.可以顺序存储 B.数据元素是一个字符 C.可以链接存储 D.数据元素可以是多个字符 8.已知某二叉树的后序遍历序列是dabec,中序遍历序列是debac,前序遍历序列是____。 A. acbed B. decab C. deabc D. cedba 9.对于一个满二叉树,m个树叶,n个结点,深度为h,则____。A. n = h + m B. h + m = 2n C. m = h-1 D. n = 2h -1 10.一个有n个顶点的无向图最多有____条边。A. n B. n(n-1) C. n(n-1)/2 D. 2n 11.顺序查找法适合于存储结构为____的线性表。A. 散列存储 B. 顺序存储或链接存储C. 压缩存储 D. 索引存储 12.在待排序的元素序列基本有序的前提下,效率最高的排序方法是____。A. 插入排序 B.选择排序 C.快速排序 D. 归并排序 二、填空题(请在每小题的横线上填入正确内容,每空1分,共7分。) 1.在线性结构中,第一个结点 前驱结点,其余每个结点有且只有1个前驱结点。 2.在无权图G的邻接矩阵中,若A[i][j]等于1,则等于A[j][i] = 。 3.根据二叉树的定义,具有三个结点的二叉树有 种不同的形态。 4.空格串是指 ,其长度等于 。 5.在散列存储中,装填因子α的值越大,则存储元素时发生冲突的可能性就 。 6.已知模式串t= ‘abacabaaad", 其用KMP法求得的每个字符对应的next函数值为 。 三、简答题(本大题共3小题,每小题5分,共15分) 1.比较静态查找与动态查找的主要区别,它们的基本运算有哪些不同? 2.逻辑结构分哪几种,存储结构有哪几种? 3.在具有n(n>1)个结点的各棵不同形态树中,其中深度最小的那棵树的深度是多少?它共有多少叶子和非叶子结点? 四、判断题(本大题共10小题,命题正确的在题后括号内写 “T”,错误的在题后括号内写“F”,每小题1分,共10分) 1.每种数据结构都应具备三种基本运算:插入、删除、搜索( )。 2.满二叉树不一定是完全二叉树。( ) 3.带权连通图的最小生成树的权值之和一定小于它的其它生成树的权值之和。( ) 4.任一棵二叉搜索树的平均搜索时间都小于用顺序搜索法搜索同样结点的顺序表的平均搜索时间。( ) 5.线性链表中所有结点的类型必须相同。( ) 6.用邻接矩阵存储一个图时,在不考虑压缩存储的情况下,所占用的存储空间大小只与图中顶点个数有关,而与图的边数无关( )。 7.在散列法中解决冲突时,其装载因子的取值一定在(0,1)之间。( ) 8.任何一个关键活动延迟,那么整个工程将会延迟。( ) 9.平衡二叉树的左右子树深度之差的绝对值不超过1。( ) 10.n个结点的有向图,若它有n(n-1)条边,则它一定是强连通的。( ) 五、分析应用题(本题共26分,1、4小题各6分,2、3小题各7分) 1.下述算法的功能是什么? (6分) LinkList Demo(LinkList L) { // L 是无头结点单链表 ListNode *Q,*P; if(L&&L->next){ Q=L; L=L->next; P=L; while (P->next) P=P->next; P->next=Q; Q->next=NULL; } return L; } 2.将给定的图简化为最小的生成树,要求从顶点1出发。(7分)3.设散列表为HT[13], 散列函数为 H (key) = key %13。用双散列法解决冲突, 对下列关键码序列 12, 23, 45, 57, 20, 03, 78, 31, 15, 36 造表。再散列函数为 RH (key) = (7*key) % 10 + 1, 寻找下一个地址的公式为 Hi = (Hi-1 + RH (key)) % 13, H1 = H (key)。画出相应的散列表, 并计算等概率下搜索成功的平均搜索长度。(7分) 4.设待排序的排序码序列为{12, 2, 16, 30, 28, 10, 16*, 20, 6, 18},写出使用快速排序法每趟排序后的结果。(6分) 六、算法设计题(本题共18分,第1小题10分,第2小题8分) 1.试设计一个实现下述要求的查找运算函数Locate。设有一个带表头结点的双向链表L, 每个结点有4个数据成员:指向前驱结点的指针llink、指向后继结点的指针rlink,存放字符数据的成员data和访问频度freq。所有结点的freq 初始时都为0。每当在链表上进行一次Locate(L, x) 操作时,令元素值为x的结点的访问频度freq加1,并将该结点前移,链接到与它的访问频度相等的结点后面,使得链表中所有结点保持按访问频度递减的顺序排列,以使频繁访问的结点总是靠近表头。(10分) 2.设一棵二叉树以二叉链表为存贮结构,设计一个算法将二叉树中所有结点的左,右子树相互交换。要求给出二叉链表的类型定义。(8分)答案:06-07第一学期期末考试参考答案与评分标准试卷代码:03266B 授课课时:112课程名称:数据结构与算法 适用对象:本科 一、单项选择题(每小题2分,共24分。) 1. B 2. C 3. B 4. C 5. A 6. B 7. B 8. D 9. D 10.C 11. B 12. A 二、填空题(每空1分,共7分。) 1. 无 2. 1 3. 5 4. 串中字符全为空格 , 空格的个数 5. 大 6. 0112123422 。 三、简答题(本大题共5小题,每小题5分,共15分) 1.答:两种查找方法最大的区别在于: 静态查找方法不修改查找表;动态查找在查找不成功时,将结点插入查找表中,即有可能修改查找表; 静态查找的基本运算有建表、查找和读表元;动态查找除上述基本操作外还有初始化、插入和删除操作; 2.答:根据数据元素之间关系的不同特性,通常有下列四类基本结构:(1)集合;(2)线性结构;(3)树形结构;(4)图状结构或网状结构。有两种不同的存储结构:顺序存储结构和链式存储结构。 3.答:深度最小的那棵树的深度为2。对于这n个结点,除了一个根结点之外,其余得n-1个结点均为叶子结点,故其深度为2。该树叶子结点数为n-1,非叶子结点数为1。 四、判断题(每小题1分,共10分) 1. (T) 2. (F) 3. (T) 4. (F) 5. (T) 6. (T) 7. (F) 8. (T) 9. (T ) 10.(T) 五、分析应用题(本题共26分,1、4小题各6分,2、3小题各7分) 1.(6分) 答:该算法的功能是:将开始结点摘下链接到终端结点之后成为新的终端结点,而原来的第二个结点成为新的开始结点,返回新链表的头指针。 2.(7分) 答: 3.(7分) 答:使用散列函数H(key)=key mod 13 有: H(12)=12, H(23)=10,H(45)=6,H(57)=5,H(20)=7,H(03)=3,H(78)=0,H(31)=5,H(15)=2,H(36)=10 利用双散列法造表:Hi =(Hi-1+RH(key))%13, Hi =H(key)0 1 2 3 4 5 6 7 8 9 10 11 1278 15 03 57 45 20 31 36 23 121 1 1 1 1 1 3 5 1 1 搜索成功的平均搜索长度为:ASL =1/10(1+1+1+1+1+1+3+5+1+1)=16/10 4.(6分) 答: 六、算法设计题(第1小题10分,第2小题8分) 1.(10分) 答:(1) 定义链表结构 struct DoubleListNode { char data ; int freq; DoubleListNode * llink, *rlink ; }; 初始时,所有结点的freq域的值都为0。(2) 定义函数 DoubleListNode * locate ( DoubleListNode *f ; char &x ) { DoubleListNode * p, *q; p = f→rlink; /*跳过表头结点*/ while ( p != NULL && p→data != x ) p = p→rlink; /*搜索*/ if ( p ) { p→freq ++; q = p→llink; p→rlink→llink = q; q→rlink = p→rlink; /*从链中摘下p*/ while ( q != f &&q→freq < p→freq ) q =q→llink; p→llink = q; p→rlink = q→rlink; q→rlink→llink = p; q→rlink = p; /*在q后面插入p*/ } return p; } 2. (8分) 答:类型定义(略) void exchange(BiTree bt)//将二叉树bt所有结点的左右子树交换 { if(bt) { BiTree s; s=bt->lchild; bt->lchild=bt->rchild; bt->rchild=s; //左右子女交换 exchange(bt->lchild); //交换左子树上所有结点的左右子树 exchange(bt->rchild); //交换右子树上所有结点的左右子树 } }2023-11-20 05:11:481
线性探测再散列法和线性探测法一样吗
应该是不按照红字进行计算的吧,因为在处理冲突的时候如果按照红字进行计算,会出现问题的。2023-11-20 05:11:551
判断线性相关的三种方法
判断线性相关的三种方法如下:第一种从定义出发寻找一组非零常数。第二种求常数项的秩或者行列式。第三种寻找向量的个数是多少,如果多数向量可以由少数向量线性表示那么多数向量一定是线性相关。设A为a1(1,0,6,a1),a2(1,-1,2,a2),a3(2,0,7,a3),a4(0,0,0,a4)。判断哪些向量一定是线性相关的,并且a1,a2,a3,a4是任意常数。a2,a3,a4秩的确定跟a的取值有关系,首先一行以及2,3,一定是线性相关。a1,a2,a3,a4一定是线性无关的无论a取任何值,秩一定是3的。考察极大线性无关组的定义,定义里说存在r个向量使得线性无关但是再加进去任何一个向量就变成线性相关的了。这里确定的是加入任何一个向量一定是线性相关的,但是这r个向量却不一定是线性无关的。线性无关的定义,对于所有的向量其前面的所有的常数都是0向量组才等于0向量那么这个向量组是线性无关的。换一句话就是只要存在一个常数不是0那么这个向量组一定不是线性相关或者说是方程一定不是齐次的。已知一个矩阵以及增广矩阵去证明b向量可以由A向量组线性表示,那么首先确定的就是A的秩假设为r那么加进去以后秩还是一样可以得到一个十字r(a1,a2,a3...at)=r(a1,a2,a3...at,b)容易发现其实就是线性表示的等价。从极大线性无关组出发假设A的极大线性无关组是a1...ar,那么增广矩阵的秩等于A的秩也就是说增广矩阵是线性相关的。根据定义一个向量组线性无关填进去任何一个向量就变成线性相关的那么这个新填进去的一定是可以被线性表示的,并且表示方法是唯一的。2023-11-20 05:12:031
线性相关的三种判断方法是什么?
令向量组的线性组合为零(零向量),研究系数的取值情况,线性组合为零当且仅当系数皆为零,则该向量组线性无关;若存在不全为零的系数,使得线性组合为零,则该向量组线性相关。通过向量组的正交性研究向量组的相关性。当向量组所含向量的个数多于向量的维数时,该向量组一定线性相关。例如在三维欧几里得空间R的三个矢量(1, 0, 0),(0, 1, 0)和(0, 0, 1)线性无关;但(2, u22121, 1),(1, 0, 1)和(3, u22121, 2)线性相关,因为第三个是前两个的和。线性相关定理1、向量a1,a2,…,an(n≧2)线性相关的充要条件是这n个向量中的一个为其余(n-1)个向量的线性组合。2、一个向量线性相关的充分条件是它是一个零向量。3、两个向量a、b共线的充要条件是a、b线性相关。4、三个向量a、b、c共面的充要条件是a、b、c线性相关。5、n+1个n维向量总是线性相关。2023-11-20 05:12:171
线性筛法
变量的作用范围是申明其{}内的,几个int i定义都在同一个{}范围内申明,所以编译会出错。建议去复习下变量的作用范围。{ int a; { int b; //变量a和b的范围 } //变量a的范围}2023-11-20 05:12:551
多重共线性的诊断方法有哪些?
多重共线性一般是指:如果有两个或者多个自变量高度相关(相关系数大于0.8),难以区分一个自变量对因变量的影响和作用,将自变量相关性产生的后果定义为多重共线性,一般提出多重共线性问题,研究者往往会想到回归分析。回归分析方法,回归模型等,在统计学中都占有重要地位,多数情况下,使用回归分析进行构建模型是,由于模型中解释变量之间存在高度相关关系(如相关系数大于0.8),所以导致数据模型估计失真,此时需要消除多重共线性问题,实现模型的精准估计。接下来从多重共线性的诊断,多重共线性解决办法以及举例进行说明多重共线性几个方面进行说明。1.经验法经验法就是通过宏观经验进行简单的判断,模型的R方比较高,但是变量不显著(回归中的t检验),或者模型结果不合理,这可能存在多重共线性,即如果R方较高,一般情况下方程整体会显著(即通过F检验),但t检验表明,没有或很少有斜率系数是显著不为0的。2.相关系数检验法对于模型中任意两个不同的解释变量进行相关分析,得到相关系数,如果相关系数的绝对值较大(一般大于0.8),则认为这两个变量相关性较高,但是需要知道,相关分析只能检验两个解释变量之间的相关性,对于更多(比如三个)解释变量的相关性检验并不适用。3.VIF(方差膨胀因子法)方差膨胀因子法又叫VIF,在线性回归中,第i个解释变量的VIF值表示为:4.特征根判断法2023-11-20 05:13:032
怎样判断线性相关还是线性无关?
判断线性无关的方法:线性组合法、行列式法。线性无关是指向量组中的向量不能通过线性组合得到零向量的性质。判断向量组的线性无关性可以通过以下两种方法进行:1、线性组合法:设向量组为{v1, v2, ..., vn},如果存在一组不全为零的标量c1, c2, ..., cn,使得c1v1 + c2v2 + ... + cnvn = 0,则向量组线性相关;否则,向量组线性无关。2、行列式法:将向量组的向量按列排成一个矩阵A,计算矩阵A的行列式值det(A)。如果det(A)≠0,则向量组线性无关;如果det(A) = 0,则向量组线性相关。需要注意的是,判断线性无关性时,需要确保向量组的维度相同,即所有向量的长度相等。线性无关的特点1、独立性:线性无关的向量组中的每个向量都是独立的,没有一个向量可以由其他向量通过线性组合得到。换句话说,向量组的每个向量都是不可替代的,它们所包含的信息互不重复。2、唯一表示:线性无关的向量组中的每个向量都可以通过线性组合唯一地表示其他向量。这意味着每个向量都可以用其他向量的线性组合来表示,而且这种表示是唯一的,没有多种不同的表示方法。3、最大线性无关组:线性无关向量组中的向量个数最多等于向量的维度。如果向量组中的向量个数等于向量的维度,那么这个向量组就是最大线性无关组。最大线性无关组的向量个数是向量的维度的最大值,也是向量空间的一组基。4、维度:线性无关向量组的维度是指向量组中线性无关的向量的个数。这个维度决定了向量组所在的向量空间的维度。比如,在三维空间中,如果一个向量组有三个线性无关的向量,那么这个向量组的维度就是3,它可以生成一个三维向量空间。2023-11-20 05:13:391
线性探查法是什么概念
线性探查法(Linear Probing)该方法的基本思想是: 将散列表T[0..m-1]看成是一个循环向量,若初始探查的地址为d(即h(key)=d),则最长的探查序列为: d,d+l,d+2,…,m-1,0,1,…,d-1 即:探查时从地址d开始,首先探查T[d],然后依次探查T[d+1],…,直到T[m-1],此后又循环到T[0],T[1],…,直到探查到T[d-1]为止。探查过程终止于三种情况: (1)若当前探查的单元为空,则表示查找失败(若是插入则将key写入其中); (2)若当前探查的单元中含有key,则查找成功,但对于插入意味着失败; (3)若探查到T[d-1]时仍未发现空单元也未找到key,则无论是查找还是插入均意味着失败(此时表满)。2023-11-20 05:14:081
线性探测再散列法是什么?
线性探测再散列是哈希表解决冲突的一种计算方法,哈希表又称散列表,哈希表存储的基本思想是:以数据表中的每个记录的关键字 k为自变量,通过一种函数H(k)计算出函数值。把这个值解释为一块连续存储空间(即数组空间)的单元地址(即下标),将该记录存储到这个单元中。在此称该函数H为哈希函数或散列函数。按这种方法建立的表称为哈希表或散列表。Hi=(H(key)+di) % m,i=1,2,……k(k<=m-1),H(key)哈希函数,m哈希表长,di增量序列。当di值可能为1,2,3,...m-1,称线性探测再散列。开放地址法有一个公式:Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)。其中,m为哈希表的表长。di是产生冲突的时候的增量序列。如果di取1,则每次冲突之后,向后移动1个位置。如果di取值可能为1,-1、4、-4、9、-9、16,、16、...k*k、-k*k(k<=m/2),称二次探测再散列,如果di取值可能为伪随机数列。称伪随机探测再散列。处理冲突的方法:1、开放寻址法:Hi=(H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:(1)di=1,2,3,…, m-1,称线性探测再散列;(2)di=1^2, -1^2, 2^2,-2^2, 3^2, …, ±(k)^2,(k<=m/2)称二次探测再散列。(3)di=伪随机数序列,称伪随机探测再散列。2、再散列法:Hi=RHi(key), i=1,2,…,k. RHi均是不同的散列函数,即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,这种方法不易产生“聚集”,但增加了计算时间。3、链地址法(拉链法):将所有关键字为同义词的记录存储在同一线性链表中。2023-11-20 05:14:341
哈希函数的哈希表的概念及作用
哈希表中元素是由哈希函数确定的。将数据元素的关键字K作为自变量,通过一定的函数关系(称为哈希函数),计算出的值,即为该元素的存储地址。表示为:Addr = H(key)为此在建立一个哈希表之前需要解决两个主要问题:⑴构造一个合适的哈希函数均匀性 H(key)的值均匀分布在哈希表中;简单 以提高地址计算的速度⑵冲突的处理冲突:在哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)= H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址。解决冲突的方法: ⑴链接法(拉链法)。将具有同一散列地址的记录存储在一条线性链表中。例,除留余数法中,设关键字为 (18,14,01,68,27,55,79),除数为13。散列地址为 (5,1,1,3,1,3,1),哈希散列表如图。⑵开放定址法。如果h(k)已经被占用,按如下序列探查:(h(k)+p⑴)%TSize,(h(k)+p⑵)%TSize,…,(h(k)+p(i))%TSize,…其中,h(k)为哈希函数,TSize为哈希表长,p(i)为探查函数。在 h(k)+p(i-1))%TSize的基础上,若发现冲突,则使用增量 p(i) 进行新的探测,直至无冲突出现为止。其中,根据探查函数p(i)的不同,开放定址法又分为线性探查法(p(i) = i : 1,2,3,…),二次探查法(p(i)=(-1)^(i-1)*((i+1)/2)^2,探查序列依次为:1, -1,4, -4, 9 …),随机探查法(p(i): 随机数),双散列函数法(双散列函数h(key) ,hp (key)若h(key)出现冲突,则再使用hp (key)求取散列地址。探查序列为:h(k),h(k)+ hp(k),…,h(k)+ i*hp(k))。⑶桶定址法。桶:一片足够大的存储空间。桶定址:为表中的每个地址关联一个桶。如果桶已经满了,可以使用开放定址法来处理。例如,插入A5,A2,A3,B5,A9,B2,B9,C2,采用线性探查法解决冲突。如图。2023-11-20 05:14:481
数据结构中二叉树的关键码和权值有什么区别???
关键码指节点的值, 权值指路径上的值2023-11-20 05:15:032
数据结构广义表的问题
第一章 数据结构基本概念 1、基本概念:理解什么是数据、数据对象、数据元素、数据结构、数据的逻辑结构与物理结构、逻辑结构与物理结构间的关系。 2、面向对象概念:理解什么是数据类型、抽象数据类型、数据抽象和信息隐蔽原则。了解什么是面向对象。由于目前关于这个问题有许多说法,我们采用了一种最流行的说法,即Coad与Yourdon 给出的定义:面向对象 = 对象 + 类 + 继承 + 通信。 要点: ·抽象数据类型的封装性 ·面向对象系统结构的稳定性 ·面向对象方法着眼点在于应用问题所涉及的对象 3、数据结构的抽象层次:理解用对象类表示的各种数据结构 4、算法与算法分析:理解算法的定义、算法的特性、算法的时间代价、算法的空间代价。 要点:·算法与程序的不同之处需要从算法的特性来解释 ·算法的正确性是最主要的要求 ·算法的可读性是必须考虑的 ·程序的程序步数的计算与算法的事前估计 ·程序的时间代价是指算法的渐进时间复杂性度量 第二章 数组 1、作为抽象数据类型的数组:数组的定义、数组的按行顺序存储与按列顺序存储 要点: ·数组元素的存放地址计算 2、顺序表:顺序表的定义、搜索、插入与删除 要点: ·顺序表搜索算法、平均比较次数的计算 ·插入与删除算法、平均移动次数的计算 3、多项式:多项式的定义 4、字符串:字符串的定义及其操作的实现 要点: ·串重载操作的定义与实现 第三章 链接表 1、单链表:单链表定义、相应操作的实现、单链表的游标类。 要点: ·单链表的两种定义方式(复合方式与嵌套方式) ·单链表的搜索算法与插入、删除算法 ·单链表的递归与迭代算法 2、循环链表:单链表与循环链表的异同 3、双向链表:双向链表的搜索、插入与删除算法、链表带表头结点的优点 4、多项式的链接表示 第四章 栈与队列 1、栈:栈的特性、栈的基本运算 要点: ·栈的数组实现、栈的链表实现 ·栈满及栈空条件、抽象数据类型中的先决条件与后置条件 2、栈的应用:用后缀表示计算表达式,中缀表示改后缀表示 3、队列:队列的特性、队列的基本运算 要点: ·队列的数组实现:循环队列中队头与队尾指针的表示,队满及队空条件 ·队列的链表实现:链式队列中的队头与队尾指针的表示、 4、双向队列:双向队列的插入与删除算法 5、优先级队列:优先级队列的插入与删除算法 第五章 递归与广义表 1、递归:递归的定义、递归的数据结构、递归问题用递归过程求解 要点:·链表是递归的数据结构,可用递归过程求解有关链表的问题 2、递归实现时栈的应用 要点:·递归的分层(树形)表示:递归树 ·递归深度(递归树的深度)与递归工作栈的关系 ·单向递归与尾递归的迭代实现 3、广义表:广义表定义、广义表长度、广义表深度、广义表表头、广义表表尾 要点: ·用图形表示广义表的存储结构 ·广义表的递归算法 第六章 树与森林 1、树:树的定义、树的基本运算 要点: ·树的分层定义是递归的 ·树中结点个数与高度的关系 2、二叉树:二叉树定义、二叉树的基本运算 要点: ·二叉树性质、二叉树中结点个数与高度的关系、不同种类的二叉树棵数 ·完全二叉树的顺序存储、完全二叉树的双亲、子女和兄弟的位置 ·二叉树的前序·中序·后序·层次遍历 ·前序 ·中序 ·后序的线索化二叉树、前驱与后继的查找方法 3、霍夫曼树:霍夫曼树的构造方法、霍夫曼编码、带权路径长度的计算 4、树的存储:树的广义表表示、树的双亲表示、树与二叉树的对应关系、树的先根·中根·后根·层次遍历。 5、堆:堆的定义、堆的插入与删除算法 要点: ·形成堆时用到的向下调整算法及形成堆时比较次数的上界估计 ·堆插入时用到的向上调整算法 第七章 集合与搜索 1、集合的概念:集合的基本运算、集合的存储表示 要点: ·用位数组表示集合时集合基本运算的实现 ·用有序链表表示集合时集合基本运算的实现 2、并查集:并查集定义、并查集的三种基本运算的实现 3、基本搜索方法 要点: ·对一般表的顺序搜索算法(包括有监视哨和没有监视哨) ·对有序顺序表的顺序搜索算法、用判定树(即扩充二叉搜索树)描述搜索,以及平均搜索长度(成功与不成功)的计算。 ·对有序顺序表的折半搜索算法、用判定树(即扩充二叉搜索树)描述搜索,以及平均搜索长度(成功与不成功)的计算。 4、二叉搜索树: 要点: ·动态搜索树与静态搜索树的特性 ·二叉搜索树的定义、二叉搜索树上的搜索算法、二叉搜索树搜索时的平均搜索长度(成功与不成功)的计算。 ·AVL树结点上的平衡因子、AVL树的平衡旋转方法 ·高度为h的AVL树上的最少结点个数与最多结点个数 · AVL树的搜索方法、插入与删除方法 第八章 图 1、图:图的定义与图的存储表示 要点: ·邻接矩阵表示(通常是稀疏矩阵) ·邻接表与逆邻接表表示 ·邻接多重表(十字链表)表示 2、深度优先遍历与广度优先遍历 要点: ·生成树与生成树林的定义 ·深度优先搜索是个递归的过程,而广度优先搜索是个非递归的过程 ·为防止重复访问已经访问过的顶点,需要设置一个访问标志数组visited 3、图的连通性 要点: ·深度优先搜索可以遍历一个连通分量上的所有顶点 ·对非连通图进行遍历,可以建立一个生成森林 ·对强连通图进行遍历,可能建立一个生成森林 ·关节点的计算和以最少的边构成重连通图 4、最小生成树 要点: ·对于连通网络、可用不会构成环路的权值最小的n-1条边构成最小生成树 ·会画出用Kruskal算法及Prim算法构造最小生成树的过程 5、单源最短路径 要点: ·采用逐步求解的方式求某一顶点到其他顶点的最短路径 ·要求每条边的权值必须大于零 6、活动网络 要点: ·拓扑排序、关键路径、关键活动、AOE网 ·拓扑排序将一个偏序图转化为一个全序图。 ·为实现拓扑排序,要建立一个栈,将所有入度为零的顶点进栈 ·关键路径的计算 第九章 排序 1、基本概念:关键码、初始关键码排列、关键码比较次数、数据移动次数、稳定性、附加存储、内部排序、外部排序 2、插入排序: 要点: ·当待排序的关键码序列已经基本有序时,用直接插入排序最快 3、选择排序: 要点: ·用直接选择排序在一个待排序区间中选出最小的数据时,与区间第一个数据对调,而不是顺次后移。这导致方法不稳定。 ·当在n个数据(n很大)中选出最小的5 ~ 8个数据时,锦标赛排序最快 ·锦标赛排序的算法中将待排序的数据个数n补足到2的k次幂2k-1<n≤2k ·在堆排序中将待排序的数据组织成完全二叉树的顺序存储。 4、交换排序: 要点: ·快速排序是一个递归的排序方法 ·当待排序关键码序列已经基本有序时,快速排序显著变慢。 5、二路归并排序: 要点: ·归并排序可以递归执行 ·归并排序需要较多的附加存储。可以采用一种"推拉法"(参见教科书上习题)实现归并排序,算法的时间复杂度为O (n)、空间复杂度为O(1) ·归并排序对待排序关键码的初始排列不敏感,排序速度较稳定 6、外排序 要点: ·多路平衡归并排序的过程、I/O缓冲区个数的配置 ·外排序的时间分析、利用败者树进行多路平衡归并 ·利用置换选择方法生成不等长的初始归并段 ·最佳归并树的构造及WPL的计算 第十章 索引与散列 1、线性索引: 要点: ·密集索引、稀疏索引、索引表计算 ·基于属性查找建立倒排索引、单元式倒排表 2、动态搜索树 要点: ·平衡的m路搜索树的定义、搜索算法 ·B树的定义、B树与平衡的m路搜索树的关系 ·B树的插入(包括结点分裂)、删除(包括结点调整与合并)方法 ·B树中结点个数与高度的关系 ·B+树的定义、搜索、插入与删除的方法 3、散列表 要点: ·散列函数的比较 ·装填因子 a 与平均搜索长度的关系,平均搜索长度与表长m及表中已有数据对象个数n的关系 ·解决地址冲突的(闭散列)线性探查法的运用,平均探查次数的计算 ·线性探查法的删除问题、散列表类的设计中必须为各地址设置三个状态 ·线性探查法中的聚集问题 ·解决地址冲突的(闭散列)双散列法的运用,平均探查次数的计算 ·双散列法中再散列函数的设计要求与表长m互质,为此m设计为质数较宜 ·解决地址冲突的(闭散列)二次散列法的运用,平均探查次数的计算 ·注意:二次散列法中装填因子 a 与表长m的设置 ·解决地址冲突的(开散列)链地址法的运用,平均探查次数的计算 我们原来也学过数据结构,个人觉得数组,栈与队列 ,递归与广义表,树与 森林(尤其是二叉树),图 ,排序这些比较重要,应该好好看2023-11-20 05:15:123
数据结构中什么是排序算法的稳定性?
比如说 5 2 3 5# 1 排序后可能是 5 5# 3 2 1 也可能是5# 5 3 2 1,前者是稳定的,后者是不稳定的。冒泡,选择有稳定性,快拍没有2023-11-20 05:15:211
线性相关的三种判断方法
令向量组的线性组合为零(零向量),研究系数的取值情况,线性组合为零当且仅当系数皆为零,则该向量组线性无关;若存在不全为零的系数,使得线性组合为零,则该向量组线性相关。通过向量组的正交性研究向量组的相关性。当向量组所含向量的个数多于向量的维数时,该向量组一定线性相关。 线性相关定理 1、向量a1,a2,…,an(nㄒ2)线性相关的充要条件是这n个向量中的一个为其余(n-1)个向量的线性组合。 2、一个向量线性相关的充分条件是它是一个零向量。 3、两个向量a、b共线的充要条件是a、b线性相关。 4、三个向量a、b、c共面的充要条件是a、b、c线性相关。 5、n+1个n维向量总是线性相关。【个数大于维数必相关】2023-11-20 05:15:291
线性相关的三种判断方法
令向量组的线性组合为零(零向量),研究系数的取值情况,线性组合为零当且仅当系数皆为零,则该向量组线性无关;若存在不全为零的系数,使得线性组合为零,则该向量组线性相关。通过向量组的正交性研究向量组的相关性。当向量组所含向量的个数多于向量的维数时,该向量组一定线性相关。 线性相关定理 1、向量a1,a2,…,an(n≧2)线性相关的充要条件是这n个向量中的一个为其余(n-1)个向量的线性组合。 2、一个向量线性相关的充分条件是它是一个零向量。 3、两个向量a、b共线的充要条件是a、b线性相关。 4、三个向量a、b、c共面的充要条件是a、b、c线性相关。 5、n+1个n维向量总是线性相关。【个数大于维数必相关】2023-11-20 05:15:371
判断线性相关的方法是什么?
令向量组的线性组合为零(零向量),研究系数的取值情况,线性组合为零当且仅当系数皆为零,则该向量组线性无关;若存在不全为零的系数,使得线性组合为零,则该向量组线性相关。通过向量组的正交性研究向量组的相关性。当向量组所含向量的个数多于向量的维数时,该向量组一定线性相关。线性相关定理1、向量a1,a2,…,an(n≧2)线性相关的充要条件是这n个向量中的一个为其余(n-1)个向量的线性组合。2、一个向量线性相关的充分条件是它是一个零向量。3、两个向量a、b共线的充要条件是a、b线性相关。4、三个向量a、b、c共面的充要条件是a、b、c线性相关。5、n+1个n维向量总是线性相关。2023-11-20 05:15:561
线性和范围试验的具体操作方法有哪两种,其各有何优点和缺点
链式:优点:插入和删除不需要移动,空间有效利用缺点:大量访问操作时不如顺序存储结构。顺序:优点:可随机存取表中任一元素。缺点:插入或删除操作时,需大量移动元素。合适在很少进行插入和删除运算的情况下。2023-11-20 05:16:281
判断向量组是否线性相关有什么方法
将向量组写成矩阵的形式,判断秩是否满秩(行满秩且列满秩),满秩则线性无关,否则线性相关2023-11-20 05:16:361
检验多重共线性的方法
检验多重共线性的方法如下:1、简单相关系数检验法proc corr data=abc;var x1-x4;run;2、方差扩大因子法proc reg data=abc;model y=x1-x4/vif;run;3、直观分析法(略)4、逐步回归检测法这在SAS中有多重筛选解释变量的方法:forward、backword、stepwise、maxr、minr、rsquare,主要采用stepwiseproc reg data=abc;model y=x1-x4/selection=stepwise sle=0.05 sls=0.10;run; quit;5、特征值和病态指数proc reg data=abc;model y=x1-x4/collin;run;三、多重共线性的补救措施1、提出变量法(根据前面的检测剔除掉vif值大的变量……略)2、增大样本容量(略)3、变换模型形式常使用变量的差分方式,一阶差分形式如下:data abc;set abc;x1lag1=lag(x1);x2lag1=lag(x2);x3lag1=lag(x3);x4lag1=lag(x4);ylag1=lag(y);if nmiss(x1lag1,x2lag1,x3lag1,x4lag1,ylag1)>0 then delete;dx1=x1-x1lag1;dx2=x1-x2lag1;dx3=x1-x3lag1;dx4=x1-x4lag1;dy=x1-ylag1;run;proc reg data=abc;model y=x1-x4;run;quit;2023-11-20 05:17:131
线性代数中齐次线性方程组中自由未知量怎么确定,各位大人给个有效的方法
把系数矩阵经初等行变换化成梯矩阵非零行的从左至右第1个不等于0的数所处的列对应的未知量是约束变量, 其余未知量就是自由未知量. 如A 化成1 2 3 4 50 0 6 7 80 0 0 0 9非零行的首非零元是1,6,9, 处在1,3,5列, x1,x3,x5 就是约束变量其余的 x2,x4 就是自由未知量.满意请采纳^_^.2023-11-20 05:17:361
线性无关怎么判断
判断线性无关的方法:线性组合法、行列式法。线性无关是指向量组中的向量不能通过线性组合得到零向量的性质。判断向量组的线性无关性可以通过以下两种方法进行:1、线性组合法:设向量组为{v1, v2, ..., vn},如果存在一组不全为零的标量c1, c2, ..., cn,使得c1v1 + c2v2 + ... + cnvn = 0,则向量组线性相关;否则,向量组线性无关。2、行列式法:将向量组的向量按列排成一个矩阵A,计算矩阵A的行列式值det(A)。如果det(A)≠0,则向量组线性无关;如果det(A) = 0,则向量组线性相关。需要注意的是,判断线性无关性时,需要确保向量组的维度相同,即所有向量的长度相等。线性无关的特点1、独立性:线性无关的向量组中的每个向量都是独立的,没有一个向量可以由其他向量通过线性组合得到。换句话说,向量组的每个向量都是不可替代的,它们所包含的信息互不重复。2、唯一表示:线性无关的向量组中的每个向量都可以通过线性组合唯一地表示其他向量。这意味着每个向量都可以用其他向量的线性组合来表示,而且这种表示是唯一的,没有多种不同的表示方法。3、最大线性无关组:线性无关向量组中的向量个数最多等于向量的维度。如果向量组中的向量个数等于向量的维度,那么这个向量组就是最大线性无关组。最大线性无关组的向量个数是向量的维度的最大值,也是向量空间的一组基。4、维度:线性无关向量组的维度是指向量组中线性无关的向量的个数。这个维度决定了向量组所在的向量空间的维度。比如,在三维空间中,如果一个向量组有三个线性无关的向量,那么这个向量组的维度就是3,它可以生成一个三维向量空间。2023-11-20 05:17:571
什么是线性趋势分析法
趋势分析法是通过对有关指标的各期对基期的变化趋势的分析,从中发现问题,为追索和检查帐目提供线索的一种分析方法。例如通过对应收帐款的趋势分析,就可对坏帐的可能与应催收的货款作出一般评价。趋势分析法可用相对数也可用绝对数。它是通过对财务报表中各类相关数字资料,将两期或多期连续的相同指标或比率进行定基对比和环比对比,得出它们的增减变动方向、数额和幅度,以揭示企业财务状况、经营情况和现金流量变化趋势的一种分析方法。采用趋势分析法通常要编制比较会计报表。扩展资料:趋势分析法应用目的:1、确定引起公司财务状况和经营成果变动的主要原因;2、确定公司财务状况和经营成果的发展趋势对投资者是否有利;3、预测公司未来发展的趋势。这种分析方法属于一种动态分析,它是以差额分析法和比率分析法为基础,同时又能有效地弥补其不足。参考资料来源:百度百科-趋势分析法2023-11-20 05:18:232
线性规则的方法
指寻求一元函数在某区间上的最优值点的方法。这类方法不仅有实用价值,而且大量多维最优化方法都依赖于一系列的一维最优化。常用的一维最优化方法有黄金分割法、切线法和插值法。① 黄金分割法又称 0.618法。它适用于单峰函数。其基本思想是:在初始寻查区间中设计一列点,通过逐次比较其函数值,逐步缩小寻查区间,以得出近似最优值点。② 切线法又称牛顿法。它也是针对单峰函数的。其基本思想是:在一个猜测点附近将目标函数的导函数线性化,用此线性函数的零点作为新的猜测点,逐步迭代去逼近最优点。③ 插值法又称多项式逼近法。其基本思想是用多项式(通常用二次或三次多项式)去拟合目标函数。此外,还有斐波那契法、割线法、有理插值法、分批搜索法等。无约束最优化方法指寻求 n元实函数f在整个n维向量空间Rn上的最优值点的方法。这类方法的意义在于:虽然实用规划问题大多是有约束的,但许多约束最优化方法可将有约束问题转化为若干无约束问题来求解。无约束最优化方法大多是逐次一维搜索的迭代算法。这类迭代算法可分为两类。一类需要用目标函数的导函数,称为解析法。另一类不涉及导数,只用到函数值,称为直接法。这些迭代算法的基本思想是:在一个近似点处选定一个有利搜索方向,沿这个方向进行一维寻查,得出新的近似点。然后对新点施行同样手续,如此反复迭代,直到满足预定的精度要求为止。根据搜索方向的取法不同,可以有各种算法。属于解析型的算法有①梯度法又称最速下降法。这是早期的解析法,收敛速度较慢②牛顿法收敛速度快,但不稳定,计算也较困难③共轭梯度法收敛较快,效果较好④变尺度法这是一类效率较高的方法。其中达维登-弗莱彻-鲍威尔变尺度法,简称 DFP法,是最常用的方法。属于直接型的算法有交替方向法(又称坐标轮换法)、模式搜索法、旋转方向法、鲍威尔共轭方向法和单纯形加速法等。约束最优化方法指前述一般非线性规划模型的求解方法。常用的约束最优化方法有 4种①拉格朗日乘子法它是将原问题转化为求拉格朗日函数的驻点②制约函数法又称系列无约束最小化方法,简称SUMT法。它又分两类,一类叫惩罚函数法,或称外点法;另一类叫障碍函数法,或称内点法。它们都是将原问题转化为一系列无约束问题来求解③可行方向法这是一类通过逐次选取可行下降方向去逼近最优点的迭代算法。如佐坦迪克法、弗兰克-沃尔夫法、投影梯度法和简约梯度法都属于此类算法④近似型算法这类算法包括序贯线性规划法和序贯二次规划法。前者将原问题化为一系列线性规划问题求解,后者将原问题化为一系列二次规划问题求解。2023-11-20 05:18:391
线性代数 - 判断向量的相关性(图解法)
例题【2008-23】设α,β,γ,δ是n向量,已经α,β线性无关,γ可以由α,β线性表示,δ不能由α,β线性表示,则以下选项中正确的是:() (A)α,β,γ,δ线性无关 (B)α,β,γ线性无关 (C)α,β,δ线性相关 (D)α,β,δ线性无关 做法: 1:把需要判断的向量,竖着列出来(本例是4行),然后后面画一些空白的网格,列数待定。 2:线性无关的向量,在不同的列上做标记,(本例中第一条,α,β线性无关,所以这两个向量在不同的列上标记一下,不同的列,表示无关) 3.线性相关的向量,在相同的列上做标记,(本例中第二条,γ可以由α,β线性表示,则有两种可能,γ和α线性相关,γ和β线性相关,那么就在γ这一行,分别与α,β同列的位置做个标记,表示它们线性相关 4.δ不能由α,β线性表示,同2 具体请看下图 这样最后得出结果就可以来判断选项的正确与否了 由图可知,判断哪些向量是否相关,只要看看对应这些向量的列方向上,有没有重复标记的,就能知道对应的向量有没有相关的了。 (A)α,β,γ,δ线性无关 在可能性一中,α,γ相关,所以A错 在可能性二中,β,γ相关,所以A错 (B)α,β,γ线性无关 在可能性一中,α,γ相关,所以B错 在可能性二中,β,γ相关,所以B错 (C)α,β,δ线性相关 在可能性一中,α,β,δ线性无关,所以C错 在可能性二中,α,β,δ线性无关,所以C错 (D)α,β,δ线性无关 D正确2023-11-20 05:18:511
基础解系线性相关怎么判断
基础解系线性相关判断:令向量组的线性组合为零(零向量),研究系数的取值情况,线性组合为零当且仅当系数皆为零,则该向量组线性无关。若存在不全为零的系数,使得线性组合为零,则该向量组线性相关。通过向量组的正交性研究向量组的相关性。当向量组所含向量的个数多于向量的维数时,该向量组一定线性相关。求法:先求出齐次或非齐次线性方程组的一般解,即先求出用自由未知量表示独立未知量的一般解的形式,然后将此一般解改写成向量线性组合的形式,则以自由未知量为组合系数的解向量均为基础解系的解向量。由此易知,齐次线性方程组中含几个自由未知量,其基础解系就含几个解向量。2023-11-20 05:19:041
什么是散列表(Hash Table)
散列表(Hash table,也叫哈希表) ,是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。 一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名 到首字母 的一个函数关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名作为关键字,“取首字母”是这个例子中散列函数的函数法则 ,存放首字母的表对应散列表。关键字和函数法则理论上可以任意确定。 散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快定位。 为了知道冲突产生的相同散列函数地址所对应的关键字,必须选用另外的散列函数,或者对冲突结果进行处理,而不发生冲突的可能性是非常之小的,所以通常对冲突进行处理。常用方法有以下几种: 开放寻址法(open addressing) 。想象一下,有一趟对号入座的火车,假设它只有一节车厢,上来一位坐7号座位的旅客。过了一会儿,又上来一位旅客,他买到的是一张假票,也是7号座位,这时怎么办呢?列车长想了想,让拿假票的旅客去坐8号座位。过了一会儿,应该坐8号座位的旅客上来了,列车长对他说8号座位已经有人了,你去坐9号座位吧。哦?9号早就有人了?10号也有人了?那你去坐11号吧。可以想见,越到后来,当空座越来越少时,碰撞的几率就越大,寻找空座愈发地费劲。但是,如果是火车的上座率只有50%或者更少的情况呢?也许真正坐8号座位的乘客永远不会上车,那么让拿假票的乘客坐8号座位就是一个很好的策略了。所以,这是一个 空间换时间 的游戏。玩好这个游戏的关键是,让旅客分散地坐在车厢里。如何才能做到这一点呢?答案是,对于每位不同的旅客使用不同的探查序列。例如,对于旅客 A,探查座位 7,8,23,56……直到找到一个空位;对于旅客B,探查座位 25,66,77,1,3……直到找到一个空位。如果有 m 个座位,每位旅客可以使用 的 个排列中的一个。 显而易见,最好减少两个旅客使用相同的探查序列的情况。也就是说,希望把每位旅客尽量分散地映射到 m! 种探查序列上。换句话说,理想状态下,如果能够让每个上车的旅客,使用 个探查序列中的任意一个的可能性是相同的,我们就说实现了一致散列。(这里没有用“随机”这个词儿,因为实际是不可能随机取一个探查序列的,因为在查找这名旅客时还要使用相同的探查序列)。 真正的一致散列是难以实现的,实践中,常常采用它的一些近似方法。常用的产生探查序列的方法有: 线性探查,平方探测,以及双重散列探查 。这些方法都不能实现一致散列,因为它们能产生的不同探查序列数都不超过 个(一致散列要求有 个探查序列)。在这三种方法中,双重散列能产生的探查序列数最多,因而能给出最好的结果。 显示线性探测填装一个散列表的过程: 关键字为{89,18,49,58,69}插入到一个散列表中的情况。此时线性探测的方法是取 。并假定取关键字除以10的余数为散列函数法则。 第二次冲突则发生在58上,取 ,往下查找3个单位,将58填装在地址为1的空单元。69同理。 表的大小选取至关重要,此处选取10作为大小,发生冲突的几率就比选择质数11作为大小的可能性大。越是质数,mod取余就越可能均匀分布在表的各处。 聚集(Cluster,也翻译做“堆积”)的意思是,在函数地址的表中,散列函数的结果不均匀地占据表的单元,形成区块,造成线性探测产生一次聚集(primary clustering)和平方探测的二次聚集(secondary clustering),散列到区块中的任何关键字需要查找多次试选单元才能插入表中,解决冲突,造成时间浪费。对于开放定址法,聚集会造成性能的灾难性损失,是必须避免的。2023-11-20 05:19:191