整理自己學習過程中接觸的習題,不斷更新中。答案在每個部分后面。
第一部分:
第二章 線性表
一、選擇題
1.下述哪一條是順序存儲結構的優點?( )
A.存儲密度大 B.插入運算方便 C.刪除運算方便 D.可方便地用於各種邏輯結構的存儲表示
2.下面關於線性表的敘述中,錯誤的是哪一個?( )
A.線性表采用順序存儲,必須占用一片連續的存儲單元。
B.線性表采用順序存儲,便於進行插入和刪除操作。
C.線性表采用鏈接存儲,不必占用一片連續的存儲單元。
D.線性表采用鏈接存儲,便於插入和刪除操作。
3.若某線性表最常用的操作是存取任一指定序號的元素和在最后進行插入和刪除運算,則利用( )存儲方式最節省時間。
A.順序表 B.雙鏈表 C.帶頭結點的雙循環鏈表D.單循環鏈表
4.某線性表中最常用的操作是在最后一個元素之后插入一個元素和刪除第一個元素,則采用( )存儲方式最節省運算時間。
A.單鏈表 B.僅有頭指針的單循環鏈表C.雙鏈表 D.僅有尾指針的單循環鏈表
5.在一個長度為n的順序表中刪除第i個元素(0<=i<=n)時,需向前移動( )個元素
A.n-i B.n-i+l C.n-i-1 D.i
6.從一個具有n個結點的單鏈表中查找其值等於x的結點時,在查找成功的情況下,需平均比較()個元素結點
A.n/2 B.n C.(n+1)/2 D.(n-1)/2
7.設單鏈表中指針p指向結點m,若要刪除m之后的結點(若存在),則需修改指針的操作為( )
A.p->next=p->next->next; B.p=p->next;
C.p=p->next->next; D.p->next=p;
8.在一個單鏈表中,已知q結點是p結點的前趨結點,若在q和p之間插入s結點,則須執行( )
A.s->next=p->next; p->next=s
B.q->next=s; s->next=p
C.p->next=s->next; s->next=p
D.p->next=s; s->next=q
9.線性表的順序存儲結構是一種( )的存儲結構。
A.隨機存取 B.順序存取 C.索引存取 D.散列存取
二、填空
1.在線性表的順序存儲中,元素之間的邏輯關系是通過 決定的;在線性表的鏈接存儲中,元素之間的邏輯關系是通過 決定的。
2.在雙向鏈表中,每個結點含有兩個指針域,一個指向 結點,另一個指向 結點。
3.當對一個線性表經常進行存取操作,而很少進行插入和刪除操作時,則采用 存儲結構為宜。相反,當經常進行的是插入和刪除操作時,則采用 存儲結構為宜。
三、算法設計
1.設有一個正整數序列組成的有序單鏈表(按遞增次序有序,且允許有相等的整數存在),試編寫能實現下列功能的算法(要求用最少的時間和最小的空間)
①確定在序列中比正整數x大的數有幾個(相同的數只計算一次)
②將單鏈表中比正整數x小的偶數從單鏈表中刪除
2.設有一個表頭指針為h的單鏈表。試設計一個算法,通過遍歷一趟鏈表,將鏈表中所有結點的鏈接方向逆轉,如下圖所示。要求逆轉結果鏈表的表頭指針h指向原鏈表的最后一個結點。
3.設計算法將一個帶頭結點的單鏈表A分解為兩個具有相同結構的鏈表B、C,其中B表的結點為A表中值小於零的結點,而C表的結點為A表中值大於零的結點(鏈表A的元素類型為整型,要求B、C表利用A表的結點)。
4. 假設鏈表A、B分別表示一個集合,試設計算法以判斷集合A是否是集合B的子集,若是,則返回1,否則返回0,並分析算法的時間復雜度。
5.設有一單循環鏈表la,其結點有三個域:prior、data與next,其中data為數據域,,next域指向直接后繼,prior域應指向直接前驅,但目前空着。試寫一算法將此單循環鏈表改造為雙向循環鏈表。
參 考 答 案
第二章 線性表
一.選擇題
1.A
2.B
3.A
4.D
5.A
6.C
7.A
8.B
9.A
二、填空
1.物理位置相鄰 指針
2.直接前驅 直接后繼
3.順序 鏈式
三、算法設計
1.① int count(Linklist h,int x) { int num=0; Linknode *p; p=h->next; while(p&&p->data<=x) p=p->next; while(p) if(p->next&&p->data==p->next->data) p=p->next; else { num++; p=p->next; } return num; } ② void delevenl(Linklist h,int x) { Linknode *p,*r; p=h->next;r=h; while(p&&p->data<x) { if(p->data%2==0) { r->next=p->next; free(p); p=r->next; } else { r=p; p=p->next; } } } 2. void Inverse(Linklist &h) { Linklist p,q; p=h; h=null; while(p) { q=p; p=p->next; q->next=h; h=q; } } 3. void merge(Linklist La,Linklist&Lb,Linklist &Lc) { Linknode*p; Lc=newLnode; Lc->next=NULL; p=La->next; Lb=La; Lb->next=NULL; while(p) { La=p->next; if(p->data>0) { p->next=Lc->next; Lc->next=p; } else { p->next=Lb->next; Lb->next=p; } p=La; } } 4. int insect(Linklist La,Linklist Lb) { Linknode*p,*q; p=La->next; while(p) { q=Lb->next; while(q) { if(p->data==q->data) break; else q=q->next; } if(!q) return0; p=p->next; } return1; } 5. void change(Dublist &h) { DubLnode*p; p=h; while(p->next!=h) { p->next->prior=p; p=p->next; } h->prior=p; }
第二部分:
第2章 線性表
2.1 選擇題
1.對於線性表最常用的操作是查找指定序號的元素和在末尾插入元素,則選擇( )最節省時間
A)順序表 B)帶頭結點的雙循環鏈表
C)單鏈表 D)帶尾結點的單循環鏈表
【答案】A
2.若長度為n的線性表采用順序存儲結構,在其第i個位置插入一個新元素的算法時間復雜度為( )(1≤i≤n+1)。
A) O(0) B) O(1) C) O(n) D) O(n2)
【答案】C
3.雙向鏈表中有兩個指針域,prior和next,分別指向前驅及后繼,設p指向鏈表中的一個結點,q指向一待插入結點,現要求在p前插入q,則正確的插入為( )
A) p->prior=q; q->next=p; p->prior->next=q; q->prior=p->prior;
B) q->prior=p->prior; p->prior->next=q; q->next=p; p->prior=q->next;
C) q->next=p; p->next=q; p->prior->next=q; q->next=p;
D) p->prior->next=q; q->next=p; q->prior=p->prior; p->prior=q;
【答案】D
4.在一個具有n個結點的有序單鏈表中插入一個新結點並仍然保持有序的時間復雜度是( )
A)O(nlog2n) B) O(1) C) O(n) D) O(n2)
【答案】C
5. 在一個以 h 為頭指針的單循環鏈中,p 指針指向鏈尾結點的條件是( )
A)p->next==NULL B) p->next==h
C)p->next->next==h D) p->data==-1
【答案】B
6.對於一個具有n個結點的線性表,建立其單鏈表的時間復雜度是( )
A)O(n) B) O(1) C)O(nlog2n) D) O(n2)
【答案】A
8.在雙向鏈表存儲結構中,刪除p所指的結點時須修改指針( )
A)p->prior->next=p->next p->next->prior=p->prior;
B)p->prior=p->prior->prior p->prior->next=p;
C)p->next->prior=p p->next=p->next->next
D)p->next=p->prior->prior p->prior=p->next->next;
【答案】A
9.線性表采用鏈式存儲時,其元素地址( )
A)必須是連續的 B)一定是不連續的
C)部分地址是連續的 D)連續與否均可
【答案】D
2.2 填空題
1.線性表L=(a1,a2,…,an)用數組表示,假定刪除表中任一元素的概率相同,則刪除一個元素平均需要移動元素的個數是_____________。
【答案】(n-1)/2
2.在單鏈表中設置頭結點的作用是_____________。
【答案】主要是使插入和刪除等操作統一,在第一個元素之前插入元素和刪除第一個結點不必另作判斷。另外,不論鏈表是否為空,鏈表頭指針不變。
3.線性表的順序存儲是通過_____________來反應元素之間的邏輯關系,而鏈式存儲結構是通過_____________來反應元素之間的邏輯關系。
【答案】(1)數據元素的前后順序 (2)元素中的指針
4.當對一個線性表經常進行的是存取操作,而很少進行插入和刪除操作時,則采用_____________存儲結構最節省時間,相反當經常進行插入和刪除操作時,則采用_____________存儲結構最節省時間。
【答案】(1)順序 (2)鏈式
5.對於一個具有n個結點的單鏈表,在已知的結點*p后插入一個新結點的時間復雜度為_____________,在給定值為x的結點后插入一個新結點的時間復雜度為_____________。
【答案】(1)O(1) (2)O(n)
7. 對於雙向鏈表,在兩個結點之間插入一個新結點需修改的指針共_____________個,單鏈表為_____________個。
【答案】(1)4 (2)2
8. 循環單鏈表的最大優點是_____________。
【答案】從任一結點出發都可訪問到鏈表中每一個元素。
9.若要在一個不帶頭結點的單鏈表的首結點*p結點之前插入一個*s結點時,可執行下列操作:
s->next=_____________;
p->next=s;
t=p->data;
p->data= _____________;
s->data=_____________;
【答案】(1)p->next (2)s->data (3) t
10.某線性表采用順序存儲結構,每個元素占據4個存儲單元,首地址為100,則下標為11的(第12個)元素的存儲地址為_____________。
【答案】144
11.帶頭結點的雙循環鏈表L中只有一個元素結點的條件是_____________。
【答案】L->next->next==L
2.3 判斷題
1.取線性表的第i個元素的時間同i的大小有關( )
【答案】×
2.線性表的特點是每個元素都有一個前驅和一個后繼( )
【答案】×
3. 順序存儲方式的優點是存儲密度大,且插入、刪除運算效率高( )
【答案】×
4.線性表采用鏈表存儲時,結點的存儲空間可以是不連續的( )
【答案】√
5.鏈表是采用鏈式存儲結構的線性表,進行插入、刪除操作時,在鏈表中比在順序存儲結構中效率高( )
【答案】√
6.順序存儲方式只能用於存儲線性結構( )
【答案】×
【解析】線性結構、樹型結構和圖狀結構均可用順序存儲表示。
9.順序存儲結構的主要缺點是不利於插入或刪除操作( )
【答案】√
10.順序存儲方式插入和刪除時效率太低,因此它不如鏈式存儲方式好( )
【答案】×
2.4 程序設計題
1.設順序表va中的數據元素遞增有序。試設計一個算法,將x插入到順序表的適當位置上,以保持該表的有序性。
【算法源代碼】
void Insert_SqList(SqList va,int x)/*把x插入遞增有序表va中*/
{ int i;
if(va.length> MAXSIZE) return;
for(i=va.length-1;va.elem[i]>x&&i>=0;i--)
va.elem[i+1]=va.elem[i];
va.elem[i+1]=x;
va.length++;
}/*Insert_SqList*/
2.設 A=(a1,a2,…,am) 和 B=(b1,b2,…,bn)均為順序表,試設計一個比較A,B大小的算法(請注意:在算法中,不要破壞原表A和B)。
【算法分析】比較順序表A和B,並用返回值表示結果,值為1,表示A>B;值為-1,表示A<B;值為0,表示A=B。
1)當兩個順序表可以互相比較時,若對應元素不等,則返回值為1或-1;
2)當兩個順序表可以互相比較的部分完全相同時,若表長也相同,則返回值為0;否則,哪個較長,哪個就較大
【算法源代碼】
int ListComp(SqList A,SqList B)
{
for(i=1;i<=A.length&&i<=B.length;i++)
if(A.elem[i]!=B.elem[i])
return A.elem[i]>B.elem[i]?1:-1;
if(A.length==B.length) return 0;
return A.length>B.length?1:-1;
/*當兩個順序表可以互相比較的部分完全相同時,哪個較長,哪個就較大*/
}/*ListComp */
3.已知指針 ha和 hb分別指向兩個單鏈表的頭結點,並且已知兩個鏈表的長度分別為m和n。試設計一個算法將這兩個鏈表連接在一起(即令其中一個表的首元結點連在另一個表的最后一個結點之后),假設指針hc指向連接后的鏈表的頭結點,並要求算法以盡可能短的時間完成連接運算。
【算法分析】
1)單鏈表ha的頭結點作為連接后的鏈表的頭結點,即hc=ha;
2)查找單鏈表ha的最后一個結點,由指針p指向,即p->next==NULL;
3)將單鏈表hb的首元結點(非頭結點)連接在p之后,即p->next=hb->next;
4)回收單鏈表hb的頭結點空間
【算法源代碼】
void ListConcat(LinkList ha,LinkList hb,LinkList *hc)
/*把鏈表hb接在ha后面形成鏈表hc*/
{
*hc=ha;
p=ha;/*由指針p指向ha的尾元結點*/
p=p->next;
p->next=hb->next;
free(hb);
}/*ListConcat */
4.試設計一個算法,在無頭結點的動態單鏈表上實現線性表操作INSERT(L,i,b),並和在帶頭結點的動態單鏈表上實現相同操作的算法進行比較。
【算法分析】
1)生成新結點存放元素b,由指針new指向;
2)將new插入在單鏈表的第i個元素的位置上:若i==1,new插在鏈表首部;否則查找第i-1個結點,由指針p指向,然后將new插在p之后。
【算法源代碼】
void Insert(LinkList *L,int i,int b)
{ LinkList new;
new=(LinkList*)malloc(sizeof(LNode));
new->data=b;
if(i==1)
{/*插入在鏈表頭部*/
New->next=*L;
*L=new;
}
else
{ /*插入在第i個元素的位置*/
p=*L;
while(--i>1) p=p->next;
new->next=p->next;p->next=new;
}
}/*Insert */
5.已知線性表中的元素以值遞增有序排列,並以單鏈表作存儲結構。試設計一個高效的算法,刪除表中所有值大於 mink且小於 maxk的元素(若表中存在這樣的元素),同時釋放被刪結點空間(注意:mink和maxk是給定的兩個參變量。它們的值可以和表中的元素相同,也可以不同)。
【算法分析】
1)查找最后一個不大於mink的元素結點,由指針p指向;
2)如果還有比mink更大的元素,查找第一個不小於maxk的元素,由指針q指向;
3)p->next=q,即刪除表中所有值大於 mink且小於 maxk的元素。
【算法源代碼】
void Delete_Between(LinkList *L,int mink,int maxk)
{
p=*L;
while(p->next->data<=mink) p=p->next; /*p是最后一個不大於mink的元素*/
if(p->next) /*如果還有比mink更大的元素*/
{
q=p->next;
while(q->data<maxk) q=q->next; /*q是第一個不小於maxk的元素*/
p->next=q;
}
}/*Delete_Between */