1.比較順序表和鏈表的優缺點,說說它們分別在什麼場景下使用?
- 順序表的特點是邏輯上相鄰的數據元素,物理存儲位置也相鄰,並且,順序表的存儲空間需要預分配。
它的優點 :
(1)方法簡單,各種高級語言中都有數組,容易實現
(2)不用爲表示節點間的邏輯關係而增加額外的存儲開銷。
(3) 順序表具有按元素序號隨機訪問的特點
它的缺點:
(1)插入時需要將後面的元素逐個挪動比較麻煩
(2)動態存儲比較麻煩,開大了浪費,開小了不夠用 - 在鏈表中邏輯上相鄰的數據元素,物理存儲位置不一定相鄰,它使用指針實現元素之間的邏輯關係。並且,鏈表的存儲空間是動態分配的。
它的優點:插入刪除方便
它的缺點:
(1) 需要佔用額外的空間,來存儲下一個節點的地址
(2)不能隨機存取元素
應用場景:
在一次可開闢足夠空間且節省空間則用順序表
在需要多次增刪查改則選用鏈表。
2.從尾到頭打印鏈表:
思考方法:首先我們需要找到最後一個節點,且還能回到上一個節點,我們可以想到遞歸,我們傳頭結點”pList”給函數,函數判斷節點是否爲NULL,若爲NULL,則打印NULL,反之我們繼續調用函數,傳pList->next,則實現了:先找到最後一個節點,並在函數返回後找到上個節點的值pList->data;
void PrintHeadtoTail(ListNode *pList)//從尾到頭打印鏈表
{
if(pList == NULL)
{
printf("NULL");
return;
}
PrintHeadtoTail(pList->next);//傳pList->next
//函數返回時不會改變plist的值
printf("<-%d",pList->data); //打印pList->data
}
3.刪除一個無頭鏈表的非尾節點
函數名: void ErasenonTail(ListNode *pos);
1.當看到這個問題的時候,我想這麼簡單的問題,我想到的代碼是:
void ErasenonTail(ListNode *pos)
{
ListNode *pavi = pos;
pos = pos->next;
free(pavi);
}
2.但運行之後,我發現程序崩潰了,我就很納悶。我就一步一步的調試發了許多很可笑的問題:
void ErasenonTail(ListNode *pos)
//這裏的pos雖然值和鏈表節點的值相同,但修改pos鏈表不會改變
{
ListNode *pavi = pos;
pos = pos->next;//pos是值傳遞
free(pavi);
pavi = NULL;//這裏就更可笑了,函數內部定義的值置空
}
3.經過這一次的教訓,我發現不能小看任何一道題,所以我利用畫圖得到了一個辦法
代碼:
void ErasenonTail(ListNode *pos)//
{
assert(pos);
ListNode *tail = pos->next;
pos->data = tail->data; //對指針的引用改變指針所指向空間的值
pos->next = tail->next;
free(tail);
}
4. 在無頭單鏈表的一個節點前插入一個節點
這個題和上一個題的方法一樣,在鏈表節點後加一個節點簡單,再交換這個節點和新添加的節點的數據;
void InsertnonTail(ListNode* pos, DataType x)//無頭鏈表節點前添加
{
assert(pos);
ListNode *pavi = NULL;
Compatibo(&pavi);
pavi->data = pos->data;
pos->data = x;
pavi->next = pos->next;
pos->next = pavi;
}
5. 單鏈表實現約瑟夫環
//頭結點 ppList ,開始的人數 n, 每次數的數m
void Josephus(ListNode **ppList,int n, int m)
{
assert(ppList);
ListNode *ret = NULL;
ListNode *tail = NULL;
int i = 0;
for(i=1; i<=n; i++)
{
PushBack(ppList, i);
}
ret = Find(*ppList,n);
ret->next = *ppList;//創建了一個循環鏈表
while(*ppList != (*ppList)->next)
{
ret = *ppList;
for(i=0;i<m-1; i++)//找出要刪除的節點
{
ret = ret->next;
}
EraseCrc(ppList, ret);//刪除節點(注意頭結點不能變)
//在刪除頭一個節點的時候,應利用無頭節點刪除的方法
}
printf("%d\n",(*ppList)->data);
}