線性錶鏈表表相關習題及詳解(選擇題) ——數據結構

本文章主要結合習題來回顧一下線性表中鏈表的相關知識,這方面還可以看我另一篇文章

線性表——Data Structure(C語言描述)


單鏈表

typedef struct LNode{       //定義單鏈表結點類型
    ElemType data;          //數據域
    struct LNode *next;     //指針域
}LNode,*LinkList;

雙鏈表

typedef struct DNode{           //定義雙鏈表結點類型
    ElemType data;              //數據域
    struct DNode *prior,*next;  //前驅和後繼指針
}DNode,*DLinklist

循環單鏈表

循環單鏈表和單鏈表的區別在於,表中最後一個結點的指針不是NULL,而改爲指向頭結點,從而整個鏈表形成一個環。

在循環單鏈表中,表尾結點*r的next域指向L,故表中沒有指針域爲NULL的結點,因此,循環單鏈表的判空條件不是頭結點的指針是否爲空,而是它是否等於頭指針。

循環單鏈表的插入、刪除算法與單鏈表的幾乎一樣,所不同的是如果操作實在表未進行,則執行的操作不相同,以讓單鏈表繼續保持循環的性質。當然,正式因爲循環單鏈表是一個“環”,因此,在任何一個位置上的插入和刪除操作都是等價的,無須判斷是否是表尾

在單鏈表中只能從表頭結點開始往後順序遍歷整個鏈表,而循環單鏈表可以從表中仁義街店開始遍歷整個鏈表。有時對單鏈表常做的操作是在表頭和表尾進行的,此時可對循環單鏈表不設頭指針而僅設尾指針,從而使得操作效率更高。其原因是若設的是頭指針,對錶尾進行操作需要O(n)的時間複雜度,而如果設的是尾指針r,r->next即爲頭指針,對於表頭與表尾進行操作都只需要O(1)的時間複雜度。

循環雙鏈表

由循環單鏈表的定義不難推出循環雙鏈表,不同的是在循環雙鏈表中,頭結點的prior指針還要指向表尾結點。

在循環雙鏈表L中,某結點*p爲尾結點時,p->next==L,當循環雙鏈表爲空表時,其頭結點的prior域和next域都等於L

靜態鏈表

靜態鏈表是藉助數組來描述線性表的鏈式存儲結構,結點也有數據域data和指針域next,與前面所講的鏈表中的指針不同的是,這裏的指針是結點的相對地址(數組下標),又稱遊標。和順序表一樣,靜態鏈表也要預先分配一塊連續的內存空間。

另外這裏有一點需要注意的是,在動態鏈表中,結點的申請和釋放分別借用malloc()和free()兩個函數來實現。在驚天鏈表中,操作的是數組,不存在像動態鏈表的結點申請和釋放問題,所以我們需要自己實現這兩個函數,纔可以做插入和刪除的操作

#define MaxSize 50
typedef struct{
    ElemType data;
    int next;
}SLinkList[MaxSize];

注意,題中如果沒有強調有序順序表,那麼默認無序 比如下面的第四題


  一維數組可以是靜態分配的,也可以是動態分配的。在靜態分配時,由於數組的大小和空間實現已經固定,一旦空間佔滿,再加入新的數據將產生溢出,就會導致程序崩潰。

  而動態分配時,儲存數組的空間實在程序執行過程中通過動態存儲分配語句分配的,一旦數據空間佔滿,可以另外開闢一塊更大的存儲空間,用以替換原來的存儲空間,從而達到擴充存儲數組空間的目的,而不需要一次性地劃分所有所需空間給線性表。


順序表和鏈表的比較

1。存取方式
順序表可以順序存取,也可以隨機存取,鏈表只能從表頭順序存取元素

2。邏輯結構與物理結構
採用順序存儲時,邏輯上系那個林的元素,其對應的物理存儲位置也相鄰。而採用鏈式存儲時,邏輯上相鄰的元素,其物理存儲位置則不一定相鄰,其對應的邏輯關係是通過指針鏈接來表示的。這裏請注意區別存取方式和存儲方式。

3。查找、插入和刪除操作
對於按值查找,當順序表在無序的情況下,兩者的時間複雜度均爲O(n);而當順序表有序時,可用折半查找,此時時間複雜度爲O(log2n)。
對於按號查找,順序表支持隨機訪問,時間複雜度爲O(1),而鏈表的平均時間複雜度爲O(n)。順序表的插入、刪除操作,平均需要移動半個表長的元素。鏈表的插入、刪除操作,只需要修改相關結點的指針域即可。由於鏈表每個結點帶有指針域,因而在春粗空間上比順序存儲要付出較大的代價,存儲密度不夠大。

4。空間分配
順序存儲在靜態存儲分配情況下,一旦存儲空間裝滿就不能擴充,如果再加入新元素將出現內存溢出,需要預先分配足夠大的存儲空間。預先分配過大,可能會導致順序表後部大量閒置;預先分配過小,又會造成一處。動態存儲分配雖然存儲空間可以擴充,但是需要移動大量元素,導致操作效率降低,而且若內存中沒有更大塊的連續存儲空間將導致分配失敗。鏈式存儲的結點空間只需要在需要的時候申請分配,只要內存有空間就可以分配,操作靈活、高效。

在實際中應該怎樣選取存儲結構呢?

1。基於存儲的考慮
對線性表的長度或存儲規模難以估計時,不宜採用順序表;鏈表不用實現估計存儲規模,但鏈表的存儲密度較低,顯然鏈式存儲結構的存儲密度是小於1的。

2。基於運算的考慮
在順序表中按序號訪問ai的時間複雜度爲O(1),而鏈表中按需要訪問的時間複雜度爲O(n),所以如果經常做的運算是按需要訪問數據元素,顯然順序表優於鏈表。

在順序表中做插入、刪除操作時,平均移動表中一半的元素,當數據元素的信息量較大且表較長時,這一點是不能忽視的;在鏈表中做插入、刪除操作時,雖然也要找插入位置,但操作主要是比較操作,從這個角度考慮顯然後者優於前者。

3。基於環境的考慮
順序表容易實現,任何高級語言中都有數組類型;鏈表的操作是基於指針的,相對來說,前者實現較爲簡單,這也是用戶考慮的一個因素。
總之,兩種存儲結構各有長短,選擇哪一種由實際問題的主要因素決定。通常較穩定的線性表選擇順序存儲,而頻繁做插入、刪除操作的線性表(即動態性較強)宜選擇鏈式存儲。


習題部分

選擇題
第一題

關於線性表的順序存儲結構和鏈式存儲結構的描述中,正確的是()
1。線性表的順序存儲結構優於其鏈式存儲結構
2。鏈式存儲結構比順序存儲結構更能方便的表示各種邏輯結構
3。如頻繁使用插入和刪除結點操作,順序存儲結構更優於鏈式存儲結構
4。順序存儲結構和鏈式存儲結構都可以進行順序存取

A. 123 B. 24 C. 23 D.34

第二題

關於線性表說法正確的是()
1。順序存儲方式只能用於存儲線性結構
2。取線性表的第i個元素的時間與i的大小有關
3。驚天鏈表需要分配較大的連續空間,插入和刪除不需要移動元素
4。在一個長度爲n的有序單鏈表中插入一個新節點並仍保持有序的時間複雜度爲O(n)
5。若用單鏈表來表示隊列,則應該選用帶尾指針的循環鏈表

A. 12 B. 1345 C. 45 D.345

第三題

設現行寶中有2n個元素,()在單鏈表上實現要比在順序表上實現效率更高。

A.刪除所有值爲x的元素
B.在最後一個元素的後面插入一個新元素
C.順序出處前k個元素
D.交換第i個元素和第2n-i-1個元素的值(i=0,…n-1)

第四題

給定有n個元素的一維數組,建立一個有序單鏈表的最低時間複雜度是()

A.O(1)
B.O(n)
C.O(n^2)
D.O(nlog2n)

第五題

單鏈表中,增加一個頭結點的目的是爲了()

A.使單鏈表至少有一個節點
B.標識表結點中首結點的位置
C.方便運算的實現
D.說明單鏈表是線性表的鏈式存儲

**第六題**1

在一個長度爲n的帶頭結點的單鏈表h上,設有尾指針r,則執行()操作與鏈表的表長有關。
A.刪除單鏈表中的第一個元素
B.刪除單鏈表中最後一個元素
C.在單鏈表第一個元素前插入一個新元素
D.在單鏈表最後一個元素後插入一個新元素

第七題

對於一個頭指針爲head的帶頭結點的單鏈表,判定該表尾空表的條件是(),對於不帶頭結點的單鏈表,則判定空表的條件爲()
A.head==NULL
B.head->next==NULL
C.head->next ==head
D.head!=NULL

第八題

某線性表中最常見的操作是在最後一個元素之後花擦入一個元素和刪除第一個元素,用()存儲方式最省時間。
A.單鏈表
B.僅有頭指針的單循環鏈表
C.雙鏈表
D.僅有尾指針的單循環鏈表

第九題

在雙鏈表中向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;q->prior->next=p;q->next=p;
D.p->prior->next=q;q->next=p;q->prior=p->prior;p->prior=q;

第十題

在雙向鏈表存儲結構中,刪除p所指的結點時必須修改指針()
A.p->llink->rlink=p->rlink;p->rlink->llink=p->llink;
B.p->llink=p->llink->llink;p->llink->rlink=p
C.p->rlink->llink=p;p->rlink=p->rlink->rlink;
D.p->rlink=p->llink->llink;p->llink=p->rlink->rlink;

第十一題

單頭結點的雙循環鏈表L爲空的條件是()
A.L->prior==L&&L->next==NULL
B.L->prior==NULL&&L->next==NULL
C.L->prior==NULL&&L->next==L
D.L->prior==L&&L->next==L

第十二題

一個鏈表最常用的操作實在末尾插入結點和刪除結點,則選用()最節省時間。
A.帶頭結點的雙循環鏈表
B.單循環鏈表
C.帶尾指針的單循環鏈表
D.單鏈表

第十三題

靜態鏈表中指針表示的是()
A.下一個元素的地址
B.內存儲器地址
C.下一個元素在數組中的位置
D.左鏈接或右鏈接指向的元素的地址


解答部分

綜合應用題

第一題

B

兩種存儲結構有不同的適用場合,不能說誰壞,1錯誤,鏈式存儲用指針表示邏輯結構,而指針的設置是任意的,僱可以很方便的表示各種邏輯結構;順序存儲只能用物理上的鄰接關係來表示邏輯結構,2正確。在順序存儲中,插入和刪除結點需要大量的移動元素,效率較低,3的描述剛好相反。順序存儲結構既可以隨機存取也能順序存取,而鏈式結構只能進行順序存取,4正確

第二題

D

順序存儲方式同樣適用圖和樹的存儲,如滿二叉樹的順序存書,1錯誤。若採用線性表採用順序存儲方式,則取第i個元素的時間與i的大小無關,2錯誤。3是靜態鏈表的特有性質。單鏈表只能順序查找插入位置,時間複雜度爲O(N),若爲順序表,可以採用折半查找,時間複雜度可降至(log2n),4正確。隊列需要在表頭刪除元素,表尾插入元素,故採用帶位置真的循環單鏈表較爲方便,插入和刪除的時間複雜度都是O(1),5正確

第三題

A

A中對於單鏈表和順序表上實現的時間複雜度都爲O(N),但後者要移動很多元素,所以在單鏈表上實現效率更高。B和D效率剛好相反,C無區別

第四題

D

若先建立鏈表,然後依次直接插入建立有序表,則每插入一個月uansu就需遍歷鏈表尋找插入位置,這就是鏈表的插入排序,時間複雜度爲O(n^2),若先將數組排好序,然後建立鏈表,建立的時間複雜度爲O(n)而數組排序的最少時間複雜度爲O(nlog2n),故時間O(nlog2n),選D

第五題

C

單鏈表設置頭結點的目的是爲了方便運算的實現,主要好處體現在:第一,有頭結點後,插入和刪除數據元素的算法同意了,不再需要判斷是否在第一個元素之前插入或刪除第一個元素;第二,無論鏈表是否爲空,其頭指針是指向頭結點的爲空指針,鏈表的頭指針不變,因此空表和費控表的處理也就統一了。

第六題

B

刪除單鏈表的最後一個結點需要置其前驅結點的指針域爲NULL,故需要的時間爲O(n),與表長有關。其他操作與表長無關,可以自行模擬

第七題

B,A

在帶頭結點的單鏈表中,頭指針指向頭結點,頭結點的next域指向第一個元素結點,head->next==NULL表示該單鏈表爲空。在不帶頭結點的單鏈表中,head直接指向第一個元素結點,head==NULL表示該單鏈表爲空。

第八題

D

在最後一個元素之後插入元素,需要先找到最後一個元素,故A B C的時間複雜度爲O(n)。B因爲沒有特殊的指針指示頭結點或者尾結點。故需從某一結點向固定的方向順序依次搜索插入和刪除的位置,時間複雜度也爲O(n)。D的兩種算法的時間複雜度都是O(1)

第九題

D

爲了在p之前插入結點q,可以將p的前一個結點的next域指向q,將q的next域指向p,將q的prior域指向p的前一個結點,將p的prior域指向q。僅D滿足條件。

第十題

A

與上題類似,只不過這裏是刪除一個結點,注意將P的前、後兩結點鏈接起來。關鍵是要保證在鏈表的修改過程中不斷鏈。

請注意對比上面兩題,弄清楚雙鏈表的插入和刪除的方法。

第十一題

D

循環單鏈表L判空的條件是頭結點(頭指針)的prior和next域都指向它自身

第十二題

A

在鏈表的末尾插入和刪除一個結點時,需要修改其相鄰結點的指針域。而尋找尾結點以及尾結點的前驅結點,只有帶頭結點的雙循環鏈表所需要的時間最少

第十三題

C

靜態鏈表中的指針又稱遊標,指示下一個元素在數組中的下標。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章