1.从尾到头打印单链表
思路导图:
代码实现:
void LinkListPrint(LinkList*head)
{
assert(head != NULL);
LinkList*end = NULL;
while (end != head)
{
LinkList*cur = head;
while (cur->_next!=end)
{
cur = cur->_next;
}
printf("%d\n", cur->_data);
end = cur;//每次范围会缩小一个
}
}
2.删除一个无头单链表的非尾节点(不能遍历链表)
思路导图:
代码实现:
void Remove(LinkList*node)
{
assert(node != NULL);
LinkList*cur = node->_next;
node->_data = cur->_data;
node->_next = cur->_next;
free(cur);
}
3.在无头单链表的一个非尾节点前插入一个节点(不能遍历单链表)
思路导图:
代码实现:
void Insert(LinkList*node, size_t x)
{
assert(node != NULL);
LinkList*cur = BuyNode(x);
cur->_next = node->_next;
node->_next = cur;
swap(cur->_data, node->_data);
}
4.单链表实现约瑟夫环
思路分析:
代码实现:
LinkList*JosephCircle(LinkList*node, size_t k)
{
if (node == NULL || node->_next == node)
return node;
LinkList*cur = node;
while (cur != cur->_next)
{
int i = 0;
while (i != k)
{
cur = cur->_next;
i++;
}
//删除第k个节点
LinkList*tmp = cur->_next;
cur->_data = tmp->_data;
cur->_next = tmp->_next;
free(tmp);
}
return cur;
}
5.逆置单链表
——头插法
思维导图:
详细过程:
代码实现:
LinkList* Reserve(LinkList*node)
{
if (node == NULL || node->_next == node)
return node;
LinkList*newNode = NULL;
while (node != NULL)
{
LinkList*cur = node->_next;
node->_next = newNode;
newNode = node;
node = cur;
}
return newNode;
}
——三指针法
思维导图:
代码实现:
LinkList*ReserveList(LinkList*node)
{
LinkList*n1, *n2, *n3;
if( node==NULL||node->_next=NULL)
{
return node;
}
n1 = node;
n2 = n1->_next;
n3 = n2->_next;
n1->_next = NULL;//方便逆置过来时,原来的头结点应该指向空
while (n2 != NULL)
{
n2->_next = n1;
n1 = n2;
n2 = n3;
while (n3 != NULL)
{
n3 = n3->_next;
}
}
return n1;//返回头结点
}
6.单链表排序——冒泡
思维导图:
代码实现:
void LinkListBubbleSort(LinkList*node)
{
LinkList*tail = NULL;
DataType flag = 0;
if (node = NULL || node->_next == NULL)
{
return node;
}
while (node!=tail)//链表不能为空
{
LinkList*cur = node;
LinkList*next = cur->_next;
while (next != tail)
{
if (cur->_data > next->_data)
{
flag = 1;
DataType tmp = cur->_data;
cur->_data = next->_data;
next->_data = tmp;
}
cur = cur->_next;
next = next->_next;
}
if (flag == 0)
{
return;
}
tail = cur;//缩小范围
}
}
7.合并两个有序单链表,使得合并后依然有序——以排升序为例
//非递归
LinkList* MergeLinkList(LinkList* pHead1, LinkList* pHead2)
{
if (pHead1 == NULL)
{
return pHead2;
}
if (pHead2 == NULL)
{
return pHead1;
}
LinkList*newHead = NULL;//把排序好的链表存放在这个里面
LinkList* tail = NULL;//记录当前链表的最后一个位置
if (pHead1->_data < pHead2->_data)
{
newHead = pHead1;
pHead1 = pHead1->_next;
}
else
{
newHead = pHead2;
pHead2 = pHead2->_next;
}
tail = newHead;//确定新链表的头结点
while (pHead1 != NULL&&pHead2 != NULL)
{
if (pHead1->_data < pHead2->_data)
{
tail->_next = pHead1;
pHead1 = pHead1->_next;
}
else
{
tail->_next = pHead2;
pHead2 = pHead2->_next;
}
tail = tail->_next;//插入一个节点,tail便向后挪一个
}
if (NULL == pHead1)
{
tail->_next = pHead2;
}
else if (NULL == pHead2)
{
tail->_next = pHead1;
}
return newHead;
}
// 递归
LinkList* MergeLinkList(LinkList* pHead1, LinkList* pHead2)
{
if (pHead1 == NULL)
{
return pHead2;
}
if (pHead2 == NULL)
{
return pHead1;
}
LinkList*newHead = NULL;//把排序好的链表存放在这个里面
while (pHead1 != NULL && pHead2 != NULL)
{
if (pHead1->_data < pHead2->_data)
{
newHead = pHead1;
newHead->_next = MergeLinkList(pHead1->_next, pHead2);
}
else
{
newHead = pHead2;
newHead->_next = MergeLinkList(pHead1, pHead2->_next);
}
}
}
8.查找一个链表的中间节点,要求只能遍历一次
思维导图:
代码实现:
LinkList* FindMidNode(LinkList* node) // 遍历一遍找到链表中间节点
{
if (node != NULL&&node->_next != NULL)
{
return node;
}
LinkList*fast = node;
LinkList*slow = node;
while (fast->_next != NULL)
{
fast = fast->_next->_next;
slow = slow->_next;
}
return slow;
}
9.查找单链表的倒数第k个节点,要求只能遍历一次链表
思路分析:
1.定义两个指针 fast 和slow
2.快指针一次走两步,慢指针一次走一步
3.fast指针先走k-1步,然后快慢指针同时走
3.当快指针走到尾时,慢指针所在的节点就是倒数第k个节点
代码实现:
LinkList* FindReciprocalKNode(LinkList* node, size_t k) //遍历一遍查找倒数第K个节点
{
assert(node!= NULL&&k!=0);
LinkList*fast = node;
LinkList*slow = node;
while (fast->_next != NULL)
{
k--;
if (k <= 0)
{
slow = slow->_next;//当快指针走了k-1步后,即走到第k个节点时,慢指针再开始走
}
fast = fast->_next;
}
//当k=链表长度时,k--之后得到——k的最大值,是1
if (k <= 1)
{
return slow;
}
else //当k的值大于1时,代表查找失败(此种情况是k的值>链表长度时)
{
return NULL;
}
}
10.删除链表的倒数第k个节点(不能遍历链表)
思路分析:
1.首先用快慢指针法找到倒数第k个节点
2.然后调用删除节点的函数进行删除
代码实现:
void RemoveReciprocalKNode(LinkList*node, size_t k)
{
assert(node != NULL&&k != 0);
LinkList*fast = node;
LinkList*slow = node;
while (fast->_next != NULL)
{
--k;
if (k <= 0)//快指针先走k步,慢指针才开始走。
{
slow = slow->_next;
}
fast = fast->_next;
if (k <= 1)//当k=链表长度时,k有最大值,k=1
{
Remove(slow);//调用删除节点的函数
}
}
}