1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
(1). 顺序表支持随机访问,单链表不支持随机访问。
(2). 顺序表插入/删除数据效率很低,时间复杂度为O(N)(除尾插尾删),单链表插入/删除效率更高,时间复杂度为O(1)。
(3). 顺序表的CPU高速缓存效率更高,单链表CPU高速缓存效率低。
2.从尾到头打印单链表
void reverse(ListNode* plist)
{
if (NULL == plist)
{
printf("NULL");
return;
}
reverse(plist->next);
printf("<-%d", plist->data);
}
3.删除一个无头单链表的非尾节点
void EraseNonTail(ListNode* pos)
{
assert(pos);
assert(pos->next);
ListNode* next = pos->next;
pos->data = next->data;
pos->next = next->next;
free(next);
next = NULL;
}
4.在无头单链表的一个节点前插入一个节点
void InsertNonTeal(ListNode *pos, DataType x)
{
assert(pos);
ListNode* newnode = BuyNode(x);
ListNode* next = pos->next;
pos->next = newnode;
newnode->next = next;
newnode->data = pos->data;
pos->data = x;
}
5.单链表实现约瑟夫环
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
ListNode* JosepRing(ListNode* list, int k)//删除第K个结点,把这个结点的data改成下一个结点的data,然后删除第K个结点的下一个结点。
{
if (!list)
{
return NULL;
}
ListNode* cur = list;
while (cur->next != cur)
{
int count = k;
while (--count)
{
cur = cur->next;
}
ListNode* next = cur->next;
cur->data = next->data;
free(next);
}
return cur;
}
6.逆置/反转单链表
ListNode* Reverse(ListNode* list)
{
ListNode* newlist = NULL;
ListNode* cur = list;
while (cur)
{
//摘结点
ListNode* tmp = cur;
cur = cur->next;
//插结点
tmp->next = newlist;
newlist = tmp;
}
return newlist;
}
7.单链表排序(冒泡排序)
void BubbleSort(ListNode* list)
{
ListNode* tail = NULL;
while (list->next != tail)
{
ListNode* cur = list;
ListNode* next = cur->next;
while (next != tail)
{
if (cur->data > next->data)
{
Datetype tmp = cur->data;
cur->data = next->data;
next->data = tmp;
}
cur = cur->next;
next = next->next;
}
tail = cur;
}
}
8.合并两个有序链表,合并后依然有序
ListNode* Merge(ListNode* list1, ListNode* list2)
{
if (!list1)
{
return list2;
}
if (!list2)
{
return list1;
}
//先找出两个链表中小的一个结点,把它摘下来做新链表的头结点
ListNode* list = NULL;
if (list1->data < list2->data)
{
list = list1;
list1 = list1->next;
}
else
{
list = list2;
list2 = list2->next;
}
//尾插
ListNode* tail = list;
while (list1&&list2)
{
if (list1->data < list2->data)
{
tail->next = list1;
list1 = list1->next;
}
else
{
tail->next = list2;
list2 = list2->next;
}
tail = tail->next;
}
if (!list1)
{
tail->next = list2;
}
if (!list2)
{
tail->next = list1;
}
return list;
}
9.查找单链表的中间节点,要求只能遍历一次链表
ListNode* FindMidNode(ListNode* list)
{
if (!list)
{
return NULL;
}
ListNode* slow = list;
ListNode* fast = list;
while (fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
10.查找单链表的倒数第k个节点,要求只能遍历一次链表
ListNode* FindTail_k_Node(ListNode* list,int K)
{
ListNode* slow = list;
ListNode* fast = list;
while (--K)
{
if (fast == NULL)//fast为空说明K值大于链表长度。既K值无效
{
return NULL;
}
fast = fast->next;
}
while (fast->next)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}