1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
2.从尾到头打印单链表
3.删除一个无头单链表的非尾节点
4.在无头单链表的一个节点前插入一个节点
5.单链表实现约瑟夫环
6.逆置/反转单链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表
2.从尾到头打印单链表
3.删除一个无头单链表的非尾节点
4.在无头单链表的一个节点前插入一个节点
5.单链表实现约瑟夫环
6.逆置/反转单链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表
10.查找单链表的倒数第k个节点,要求只能遍历一次链表
//从尾到头打印单链表
void ReversePrintf(ListNode* pList)//使用递归
{
if (pList == NULL)
{
return;
}
else
{
ReversePrintf(pList->next);
}
printf("%d->", pList->data);
}
//删除一个无头单链表的非尾节点
void EraseNoHead(ListNode* pos)//替换法
{
ListNode* next = pos->next;
DataType tmp = next->data;
pos->data = tmp;
pos->next = next->next;
free(next);
}
//在无头单链表的一个节点前插入一个节点
void InsertNoHead(ListNode* pos,DataType x)//替换法
{
ListNode* tmp = BuyNode(x);
ListNode* next = pos->next;
pos->next = tmp;
tmp->next = next;
DataType data = pos->data;
pos->data = tmp->data;
tmp->data = data;
}
//单链表实现约瑟夫环
ListNode* JosRing(ListNode*pList,int k)
{
if (pList == NULL)
return NULL;
while (pList == pList->next)
{
int count = k;
while (--count)
{
pList = pList->next;
}
ListNode* next = pList->next;
pList->data= next->data;
pList->next = next->next;
free(next);
}
return pList;
}
//逆置/反转单链表
ListNode* ReverseLinklist(ListNode** ppList)
{
//1,链表为空或者只有一个节点
//2,链表不为空
if (*ppList == NULL || (*ppList)->next == NULL)
return *ppList;
else
{
ListNode* newplist = NULL;
ListNode* atil = *ppList;
while (atil)
{
ListNode* tmp = atil;
atil = atil->next;//必须在这个位置,靠后的话,atil->next已经被改变,出错,接下
tmp->next = newplist;//atil->next被赋值为newplist。
newplist = tmp;
/*atil->next = newplist;//这种是错的,留着提醒
newplist = atil;
atil = atil->next;*/
}
return newplist;
}
}
//.单链表排序(冒泡排序&快速排序)
void BubbleSortLinklist(ListNode** ppList)
{
if (*ppList == NULL || (*ppList)->next == NULL)
return;
else
{
ListNode* tail = NULL;//运用tail当作最后一个节点的next,也就是为空,然后在循环中每次向前
while (tail != *ppList)//进一个节点
{
ListNode* cur = *ppList;
ListNode* next = cur->next;
int flag = 0;//优化
while (next != tail)// 第一次tail为空,cur是空
{
if (cur->data > next->data)
{
DataType tmp = cur->data;
cur->data = next->data;
next->data = tmp;
flag = 1;
}
next = next->next;
cur = cur->next;
}
if (flag == 0)
return;
tail = cur;
}
}
}
//合并两个有序链表,合并后依然有序
ListNode* CombineList(ListNode* list1,ListNode* list2)//先摘一个头,然后再继续尾插
{
if (list1 == NULL)
{
return list2;
}
else if (list2 == NULL)
{
return list1;
}
else
{
ListNode* NewList = NULL;
if (list1->data > list2->data)//摘头
{
NewList = list2;
list2 = list2->next;
}
else
{
NewList = list1;
list1 = list1->next;
}
ListNode* tail = NewList;
while (list1&&list2)//尾插
{
if (list1->data > list2->data)
{
tail->next = list2;
list2 = list2->next;
}
else
{
tail->next = list1;
list1 = list1->next;
}
tail = tail->next;
}
if (list1 != NULL)
{
tail->next = list1;
}
else if (list2 != NULL)
{
tail->next = list2;
}
return NewList;
}
}
//查找单链表的中间节点,要求只能遍历一次链表
ListNode* SearchMid(ListNode* pList)//通过快慢指针,一个走两步,一个走一步,当快指针到尾时,慢指针在中间位置
{
ListNode* fast = pList;
ListNode* slow = pList;
//ListNode* prev = pList;//注释的内容是,当节点数为偶数时,中间结点有两个,定义一个变量,存储前一个节点的地址。
while (fast && fast->next)//偶数节点找出来的是偶数个的后一个地址。
{
fast = fast->next->next;
//prev = slow;
slow = slow->next;
}
/*if (fast == NULL)
{
slow = prev;
}*/
return slow;
}
//查找单链表的倒数第k个节点,要求只能遍历一次链表
ListNode* FindTailkNode(ListNode *pList, DataType k)//快慢指针,快指针先走k位,然后与慢指针一起走,
{ //快指针到尾时,慢指针在倒数第k个位置。
if (pList == NULL)
{
return NULL;
}
ListNode* fast = pList;
ListNode* slow = pList;
while (k--)//(--k)也行,只不过是fast->next==NULL;
{
fast = fast->next;
}
while (fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}