头文件定义及链表结构体声明
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
typedef int DataType;
typedef struct SListNode
{
struct SListNode *next;
DataType data;
}SListNode, *pSListNode, **ppSListNode;
从尾到头打印单链表
void SListReverse(pSListNode head)//从尾到头打印单链表(逆序打印)
{
#if 1
//方法1:递归 O(N) O(N)
if (head == NULL)
{
printf(" NULL <-");
return;
}
SListReverse(head->next);
printf("%2d <-", head->data);
#else
//方法:循环 O(N^2) O(1)
pSListNode end = NULL;
printf(" NULL");
while (end != head)
{
pSListNode node = head;
while (node->next != end)
node = node->next;
printf(" <-%2d", node->data);
end = node;
}
printf("\n");
#endif
}
逆置/反转单链表
pSListNode Reverse(ppSListNode head)//逆置链表
{
#if 1
//头删头插法
pSListNode node = NULL;
pSListNode cur = *head;
while (cur)
{
pSListNode tmp = cur;
cur = cur->next;
//头插
tmp->next = node;
node = tmp;
}
return node;
#else
//改变指向法
//前两个指指针负责翻转,第三个负责保存节点
pSListNode p1 = NULL, p2 = *head , p3 = p2->next;
if (*head == NULL || (*head)->next == NULL)
return *head;
while (p2 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
if (p3 != NULL)
p3 = p3->next;
}
*head = p1;
return *head;
#endif
}
任意位置删
void SListErase(ppSListNode head, pSListNode pos)
{
#if 1
pSListNode node = *head;
if (head == NULL)
return;//非法输入
if (*head == pos)//头删
{
SListPopFront(head);
return;
}
while (node->next != pos)
node = node->next;
node->next = pos->next;
free(pos);
#else
//删除一个无头单链表的非尾节点(不能遍历链表) 时间复杂度O(1)
//替换法删除----腾讯面试题
if (head == NULL)//非法输入
return;
if (*head == NULL)//空链表
return;
if (pos != NULL && pos->next != NULL)
{
pSListNode node = pos->next;
pos->data = pos->next->data;
pos->next = node->next;
free(node);
}
#endif
}
任意位置插
void SListInsert(ppSListNode head,pSListNode pos,DataType x)
{
#if 0
pSListNode node = *head;
pSListNode newnode = BuySListNode(x);
if (head == NULL)
return;//非法输入
if (*head == pos)//头插
SListPushFront(head, x);
while (node->next != pos)
node = node->next;
newnode->next = pos;
node->next = newnode;
#else
//在无头单链表的一个节点前插入一个节点(不能遍历链表)
//创建一个节点(node)不赋值,将源位置节点(pos)的数赋值到该节点(node)处,将插入值赋值到源位置节点(pos)处
//断链(pos-1---pos)/(pos---pos+1),连链(pos-1---node)/(node---pos+1)
pSListNode node=BuySListNode(x);
if (head == NULL && pos == NULL)
return;
if (*head == NULL)
return;
node->data = pos->data;
pos->data = x;
node->next = pos->next;
pos->next = node;
#endif
}
约瑟夫环
int JosephCircle(pSListNode head,size_t number)//约瑟夫环
{
pSListNode node = head, cur = head;
//空链表返回
if (head == NULL)
return 0;
//非循环变化成循环
while (node->next)
node = node->next;
node->next = head;
//循环只剩一人
while (cur->next != cur)
{
int count = number;
//教号数循环number-1次
while (--count)
cur = cur->next;
node = cur->next;
cur->data = node->data;
cur->next = node->next;
free(node);
}
return cur->data;
}
单链表排序
pSListNode BubbleSort(pSListNode head)//冒泡
{
pSListNode node = head;
pSListNode newnode = head->next;
pSListNode end = NULL;
int flag = 0;
if (head == NULL || head->next == NULL)
return head;
while (end != head->next)
{
node = head;
newnode = head->next;
while (newnode != end)
{
if (node->data > newnode->data)
{
DataType tmp = node->data;
node->data = newnode->data;
newnode->data = tmp;
flag = 1;
}
node = node->next;
newnode = newnode->next;
}
if (flag == 0)
break;
end = node;
}
return head;
}
合并两个有序链表,合并后依然有序
pSListNode MergeList(pSListNode list1, pSListNode list2)//合并两个有序链表,合并后依然有序
{
pSListNode list = NULL, node = NULL;
//防止其中一个为空
if (list1 == NULL)
return list2;
if (list2 == NULL)
return list1;
//准备头
if (list1->data < list2->data)
{
list = list1;
list1 = list1->next;
}
if (list1->data > list2->data)
{
list = list2;
list2 = list2->next;
}
//链接
node = list;//标记此时尾
while (list1 && list2)//其中一个结束循环结束
{
if (list1->data < list2->data)
{
node->next = list1;
list1 = list1->next;
}
else
{
node->next = list2;
list2 = list2->next;
}
node = node->next;
}
if (list1)
node->next = list1;
if (list2)
node->next = list2;
return list;
}
查找单链表的中间节点,要求只能遍历一次
pSListNode FindMiddle(pSListNode head)//查找中间节点,要求只能遍历一次链表
{
pSListNode fast = head;
pSListNode slow = head;
while (fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
查找单链表的倒数第K个节点,要求只能遍历一次链表
pSListNode FindDsp(pSListNode head,DataType k)
{
pSListNode front = head;
pSListNode back = head;
assert(head);
while (--k)
front = front->next;
while (front->next != NULL)
{
front = front->next;
back = back->next;
}
return back;
}
删除链表的倒数第K个节点
pSListNode FindErase(pSListNode head, DataType k)//查找倒数第k个节点,并删除
{
pSListNode fast = head;
pSListNode slow = head;
pSListNode node = NULL;
assert(head);
while (--k)
fast = fast->next;
while (fast->next != NULL)
{
fast = fast->next;
slow = slow->next;
}
//如果slow==NULL就尾删,如果非NULL即非尾节点删
SListErase(&head, slow);//任意位置删
return head;
}
判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法时间复杂度,空间复杂度?
pSListNode IsCycle(pSListNode head)//判断是否带环
{
pSListNode fast = head, slow = head;
assert(head);
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)
return fast;//返回相遇点
}
return NULL;
}
int GetCirclelen(pSListNode meet)//求环的节点数
{
//从相遇点,绕一圈,就是环的长度
pSListNode node = meet->next;
size_t count = 1;
while (node != meet)
{
node = node->next;
count++;
}
return count;//返回环的节点数
}
//2(L+X)=L+X+nR
//L=nR-X
pSListNode GetEntry(pSListNode head, pSListNode meet)//找到带环的节点位置
{
while (head != meet)
{
head = head->next;
meet = meet->next;
}
return meet;//返回节点位置
}
判断两个链表是否相交,若相交,求交点
pSListNode GetCrossNode(pSListNode list1, pSListNode list2)
{
DataType len1 = 0, len2 = 0;
pSListNode cur1 = list1, cur2 = list2;
pSListNode longlist = list1, shortlist = list2;
size_t step = 0;
while (cur1)//求list1长度
{
++len1;
cur1 = cur1->next;
}
while (cur2)//求list2长度
{
++len2;
cur2 = cur2->next;
}
if (len1 < len2)//保证longlist始终为长链表
{
longlist = list2;
shortlist = list1;
}
step = abs(len1 - len2);
while (step--)//对齐,让长链表先走差距步
longlist = longlist->next;
while (longlist != shortlist)
{
longlist = longlist->next;
shortlist = shortlist->next;
}
return longlist;
}
求两个已排序单链表中相同的数据
pSListNode UnionSet(pSListNode list1, pSListNode list2)//求两个已排序单链表中相同的数据
{
pSListNode node = NULL;
while (list1 && list2)
{
if (list1->data < list2->data)
list1 = list1->next;
else if (list1->data > list2->data)
list2 = list2->next;
else
{
SListPushBack(&node, list1->data);
list1 = list1->next;
list2 = list2->next;
}
}
return node;
}
一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表
void Print(pCList head)
{
assert(head);
pCList node = head;
while (node)
{
printf("%d (%d) ->", node->data, node->random != NULL ? node->random->data : 0);
node = node->next;
}
printf(" NULL\n");
}
pCList CopyCList(ppCList head)
{
assert(head);
if(*head==NULL)
return NULL;
pCList src = *head;
pCList newlist = NULL;
//拷贝插入节点
while (src)
{
pCList node = (pCList)malloc(sizeof(pCList));
node->data = src->data;
node->next = src->next;
src->next = node;
src = src->next->next;
}
//置random
for (src = *head; src; src = src->next->next)
{
if (src->random != NULL)
src->next->random = src->random->next;
else
src->next->random=NULL;
}
printf("插入后链表:\n");
Print(*head);
newlist = (*head)->next;
//拆
for (src = *head; src; src = src->next)
{
pCList copy = src->next;
pCList cur = copy->next;
if (cur != NULL)
copy->next = cur->next;
else
copy->next = NULL;
src->next = cur;
}
return newlist;
}