先定义链表结构为:
typedef int DataType;
typedef struct SListNode
{
struct SListNode* _next;
DataType _data;
}SListNode;
1. 从尾到头打印单链表
1)定义end先走到空,通过第一层循环先找到第1个要打印的数,每次找end的前一个数打印。再定义cur,end中的数据打印完后,把cur赋给end,让cur从头走
void PrintTailToHead(SListNode* head)
{
SListNode* end = NULL;
while (end != head)
{
SListNode* cur = head;
while (cur->_next != end)
{
cur = cur->_next;
}
//此时cur走到end的前一个位置
printf("%d", cur->_data);
end = cur;
}
printf("\n");
}
2)采用递归的方式,如果当前节点不为空,就继续打印函数传递过去的参数的下一个节点
void PrintTailToHeadR(SListNode* head)//递归
{
if (head == NULL)//不能用assert,它会终止程序
return;
PrintTailToHeadR(head->_next);
printf("%d ", head->_data);
}
2. 删除无头单链表的非尾节点(不能遍历链表)
用替换法,让当前位置的下一个节点覆盖当前节点,再free掉当前节点的下一个节点
void DelNode(SListNode* pos)
{
SListNode* next;
assert(pos && pos->_next);
//替换法删除
next = pos->_next;
pos->_data = next->_data;
pos->_next = next->_next;
free(next);
}
3. 在无头单链表的一个节点前插入一个节点(不能遍历链表)
因为只知道当前节点的下一个节点的位置,所以在当前节点后先把这个节点插入,再交换一下这两个节点的位置
void InsertNode(SListNode* pos, DataType x)
{
assert(pos);
SListNode* tmp = BuySListNode(pos->_data);
tmp->_next = pos->_next;
pos->_next = tmp;
pos->_data = x;
}
4. 单链表实现约瑟夫环(JosephCircle)
给定k值表示走到k就删掉k的位置上的数
先把链表的尾链上头形成一个环,使用替换法删除节点,返回最后剩下的这个节点。
SListNode* JosephCycle(SListNode* head, int k)//数到k就删掉
{
SListNode* tail = head, *cur = head;
if (head == NULL)
return NULL;
//构成环
while (tail->_next)
tail = tail->_next;
tail->_next = head;
while (cur->_next != cur)
{
SListNode* next;
int count = k;
while (--count)//走k-1次
cur = cur->_next;
next = cur->_next;
cur->_data = next->_data;
cur->_next = next->_next;
free(next);
}
return cur;
}
5. 逆置/反转单链表
用头插法
SListNode* ReverseList2(SListNode* head)
{
SListNode* newhead = NULL;
SListNode* cur = head;
while (cur)
{
SListNode* tmp = cur;
cur = cur->_next;
//头插
tmp->_next = newhead;
newhead = tmp;
}
return newhead;
}
6. 单链表排序(冒泡排序&快速排序)
1)冒泡排序
void BubbleSortList(SListNode* head)
{
SListNode* cur, *next;
SListNode* tail = NULL;
if (head == NULL || head->_next == NULL)
return;
while (tail != head->_next)
{
int flag = 0;
cur = head;
next = cur->_next;
while (next != tail)
{
if (cur->_data > next->_data)
{
DataType tmp = cur->_data;
cur->_data = next->_data;
next->_data = tmp;
flag = 1;
}
cur = cur->_next;
next = next->_next;
}
if (flag == 0)
break;
tail = cur;
}
}
7. 合并两个有序链表,合并后依然有序
用尾插法,每走一步都做一次比较,用小的数当作新表需要尾插的数,定义list头指向第一次尾插的数
SListNode* MergeList(SListNode* list1, SListNode* list2)
{
SListNode* list, *tail;
if (list1 == NULL)
return list2;
if (list2 == NULL)
return list1;
if (list1->_data < list2->_data)
{
list = list1;
list1 = list1->_next;
}
else
{
list = list2;
list2 = list2->_next;
}
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 = list1;
if (list2)
tail->_next = list2;
return list;
}