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