1.比較順序表和鏈表的優缺點,說說它們分別在什麼場景下使用?
1). 順序表支持隨機訪問,單鏈表不支持隨機訪問。
2). 順序表插入/刪除數據效率很低,時間複雜度爲O(N)(除尾插尾刪),單鏈表插入/刪除效率更高,時間複雜度爲O(1)。
3). 順序表的CPU高速緩存效率更高,單鏈表CPU高速緩存效率低。
2.從尾到頭打印單鏈表
//遞歸法
void PrintList(ListNode* plist)
{
if(plist==NULL)
{
return;
}
PrintList(plist->next);
printf("%d->",plist->data);
}
3.刪除一個無頭單鏈表的非尾節點
void EraseNonTail(ListNode* pos)
{
assert(pos&&pos->next);
ListNode* next=pos->next;
pos->data=next->data;
pos->next=next->next;
free(next);
}
4.在無頭單鏈表的一個節點前插入一個節點
void InsertNonHead(ListNode* pos, DataType data)
{
assert(pos);
ListNode* next = pos->next;
ListNode* tmp = BuyNode(data);
pos->next = tmp;
tmp->next = next;
DataType datatmp = pos->data;
pos->data = tmp->data;
tmp->data = datatmp;
}
5.單鏈表實現約瑟夫環
ListNode* JosephRing(ListNode* plist, int k)
{
//不帶環返回空指針
if(IsCycle(plist) == NULL)
{
return NULL;
}
ListNode* cur = plist;
//只剩一個節點循環停止
while(cur != cur->next)
{
int count = k;
while(--count)
{
cur = cur->next;
}
ListNode* next = cur->next;
cur->data = next->data;
cur->next = next->next;
free(next);
}
return cur;
}
6.逆置/反轉單鏈表
ListNode* ReverseList(ListNode* plist)
{
ListNode* newhead = NULL;
ListNode* cur = plist;
ListNode* tmp = plist;
while(cur)
{
cur = cur->next;
tmp->next = newhead;
newhead = tmp;
tmp = cur;
}
return newhead;
}
7.單鏈表排序(冒泡排序&快速排序)
void BubbleList(ListNode* plist)
{
ListNode* tail = NULL;
while(tail != plist->next)
{
ListNode* cur = plist;
ListNode* next = plist->next;
while(next != tail)
{
if(cur->data > next->data)
{
DataType tmp = cur->data;
cur->data = next->data;
next->data = tmp;
}
next = next->next;
cur = cur->next;
}
tail = cur;
}
}
8.合併兩個有序鏈表,合併後依然有序
ListNode* CombineList(ListNode* plist1, ListNode* plist2)
{
ListNode* list = NULL;
if(plist1 == NULL)
{
return plist2;
}
else if(plist2 == NULL)
{
return plist1;
}
else
{
if(plist1->data < plist2->data)
{
list = plist1;
plist1 = plist1->next;
}
else
{
list = plist2;
plist2 = plist2->next;
}
ListNode* tail = list;
while (plist1 && plist2)
{
if(plist1->data < plist2->data)
{
tail->next = plist1;
plist1 = plist1->next;
tail = tail->next;
}
else
{
tail->next = plist2;
plist2 = plist2->next;
tail = tail->next;
}
}
if(plist1 == NULL)
{
tail->next = plist2;
}
else
{
tail->next = plist1;
}
}
return list;
}
9.查找單鏈表的中間節點,要求只能遍歷一次鏈表
ListNode* SearchListMid(ListNode* plist)
{
ListNode* fast = plist;
ListNode* slow = plist;
while (fast && fast->next)
{
fast = (fast->next)->next;
slow = slow->next;
}
return slow;
}
10.查找單鏈表的倒數第k個節點,要求只能遍歷一次鏈表
ListNode* SearchListK_r(ListNode* plist, int k)
{
ListNode* fast = plist;
ListNode* slow = plist;
//fast往後走k-1步
int i = k;
for(i=0; i<k-1; i++)
{
fast = fast->next;
//如果k大於了鏈表長度,返回空指針
if(fast == NULL)
{
return NULL;
}
}
//讓fast走到最後一個節點
while(fast->next)
{
fast = fast->next;
slow = slow->next;
}
return slow