1、倒序打印链表
(1)非递归方式
代码如下:
void ReversePrint(ListNode **pFirst)
{
ListNode *last = NULL;
ListNode *cur = NULL;
assert(*pFirst != NULL);
while(last != *pFirst)
{
cur = *pFirst;
while(cur != NULL)
{
if(cur->next == last)
{
printf("%d ",cur->data);
last = cur;
}
cur = cur->next;
}
}
printf("\n");
}
(2)递归方式
可以在递归的最后一层(即最后一次递归调用)时打印最后一个结点的元素,在每次函数调用结束返回时打印当前结点的元素。代码如下:
void ReversePrintR(ListNode *pFirst)
{
if(pFirst == NULL)
{
return ;
}
if(pFirst->next == NULL)
{
printf("%d ",pFirst->data);
}
else
{
ReversePrintR(pFirst->next);
printf("%d ",pFirst->data);
}
}
2、逆置链表
代码如下:
ListNode *ReverseList(ListNode **pFirst)
{
ListNode *tmp = NULL;
ListNode *pre = NULL;
ListNode *cur = NULL;
ListNode *result = NULL;
assert(*pFirst != NULL);
cur = *pFirst;
while(cur != NULL)
{
tmp = cur->next;
if(cur->next == NULL)
{
result = cur;
}
cur->next = pre;
pre = cur;
cur = tmp;
}
return result;
}
3、删除一个无头链表的非尾结点
代码如下:
void RemoveNodeNotTail(ListNode *pos)
{
if(pos == NULL)
{
return ;
}
pos->data = pos->next->data;
pos->next = pos->next->next;
}
4、在无头链表前插入一个结点
代码如下:
void InsertNoHead(ListNode *pos, int data)
{
ListNode *NewNode = NULL;
if(pos == NULL)
{
return ;
}
NewNode = CreateNode(data);
NewNode->data = pos->data;
NewNode->next = pos->next;
pos->data = data;
pos->next = NewNode;
}
5、单链表实现约瑟夫环
整体思路分为两步走:
(1)先使链表构成一个环(最后一个结点的next等于第一个结点);
(2)如果链表中的剩余结点超过一个,每次找到第k个结点,删除它。
代码如下:
ListNode *JocephCircle(ListNode *pFirst, int k)
{
ListNode *result = NULL;
ListNode *pre = NULL;
ListNode *cur = NULL;
int i = 0;
assert(pFirst != NULL);
cur = pFirst;
//先使链表构成一个环(最后一个结点的next等于第一个结点)
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = pFirst;
//如果链表中剩余结点超过一个,每次找到第k个结点,删除它
cur = pFirst;
while(cur->next != cur)
{
for(i=0; i<k-1; i++)
{
pre = cur;
cur = cur->next;
}
//删除元素
pre->next = cur->next;
//free(cur);
cur = pre->next;
}
result = cur;
result->next = NULL;
return result;
}
6、冒泡排序
代码如下:
void BubbleSort(ListNode **pFirst)
{
ListNode *cur = NULL;
ListNode *last = NULL;
ListNode *pre = NULL;
DataType tmp = 0;
DataType max = 0;
assert(*pFirst != NULL);
while(last != (*pFirst)->next)
{
cur = (*pFirst)->next;
max = (*pFirst)->data;
while(cur != last)
{
if(cur->data>max) //当前值大于最大值时,交换两数
{
tmp = max;
max = cur->data;
cur->data = tmp;
}
pre = cur;
cur = cur->next;
}
//一次循环结束后,把最大值放入使循环结束的结点中,把该结点中的值放入链表开头
tmp = pre->data;
pre->data = max;
(*pFirst)->data = tmp;
last = pre;
}
}
7、合并两个有序链表
整体思路如下:
用result记录新链表,两个链表的当前数进行比较,哪个小,就先放入链表中,并且向后移动。直至两个链表的最后一个结点,结束循环。代码如下:
ListNode *MergeOrderedList(ListNode *p1First, ListNode *p2First)
{
ListNode *cur1 = NULL;
ListNode *cur2 = NULL;
ListNode *result = NULL;
ListNode *tail = NULL;
ListNode *node = NULL;
assert(p1First);
assert(p2First);
cur1 = p1First;
cur2 = p2First;
while((cur1 != NULL)&&(cur2 != NULL))
{
if(cur1->data<=cur2->data)
{
node = cur1;
cur1 = cur1->next;
if(tail == NULL)
{
result = node;
}
else
{
tail->next = node;
}
node->next = NULL;
tail = node;
}
else
{
node = cur2;
cur2 = cur2->next;
if(tail == NULL)
{
result = node;
}
else
{
tail->next = node;
}
node->next = NULL;
tail = node;
}
}
if(cur1 != NULL)
{
tail->next = cur1;
}
if(cur2 != NULL)
{
tail->next = cur2;
}
return result;
}
8、查找链表的中间结点(只能遍历一次链表)
思路:
取两个指针走;
一个快指针,一个慢指针;
快指针走两步,慢指针走一步;
直至快指针走到链表末尾,结束循环;
慢指针所在位置就是链表的中间结点。
代码如下:
ListNode *FindMid(ListNode *pFirst)
{
ListNode *cur = NULL;
ListNode *mid = NULL;
int count = 0;
assert(pFirst != NULL);
cur = pFirst;
mid = pFirst;
while(cur != NULL)
{
cur = cur->next;
count++;
if((count%2)==0)
{
mid = mid->next;
count = 0;
}
//cur = cur->next;
//count++;
}
return mid;
}
9、查找链表的倒数第k个结点(只能遍历一次链表)
思路:
取快、慢两个指针走;
快指针先走k步;
然后在快、慢指针一起走;
直至快指针走到链表末尾,结束循环;
慢指针所在位置即为链表的倒数第k个结点。
代码如下:
ListNode *FindK(ListNode *pFirst, int k)
{
ListNode *fast = NULL;
ListNode *slow = NULL;
assert(pFirst != NULL);
fast = pFirst;
slow = pFirst;
while(k)
{
fast = fast->next;
k--;
}
while(fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
10、删除链表的倒数第k个结点(只能遍历一遍链表,不能使用替换法删除)
思路:
用快、慢两个指针走;
快指针先走k+1步;
再快、慢指针一起走;
直至快指针走到链表末尾,结束循环;
找到倒数第k+1个结点,让第k+1个结点指向第k个结点之后的结点,即删除第k个结点。
代码如下:
void RemoveK(ListNode **pFirst, int k)
{
ListNode *del = NULL;
ListNode *fast = NULL;
ListNode *slow = NULL;
assert(*pFirst != NULL);
fast = *pFirst;
slow = *pFirst;
while(k+1)
{
fast = fast->next;
k--;
}
while(fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
del = slow->next;
slow->next = slow->next->next;
//free(del);
}
11、求两个已排序单链表中相同的数据,并用链表返回
思路:
两个链表中的当前数进行比较,哪个小,哪个就往前走,两个数相等时,就将其放入新链表中,直至循环结束。
代码如下:
ListNode *UnionSet(ListNode *list1, ListNode *list2)
{
ListNode *cur1 = NULL;
ListNode *cur2 = NULL;
ListNode *result = NULL;
ListNode *tail = NULL;
ListNode *node = NULL;
assert(list1 != NULL);
assert(list2 != NULL);
cur1 = list1;
cur2 = list2;
while((cur1 != NULL)&&(cur2 != NULL))
{
if(cur1->data<cur2->data)
{
cur1 = cur1->next;
}
else if(cur1->data>cur2->data)
{
cur2 = cur2->next;
}
else
{
node = cur1;
cur1 = cur1->next;
cur2 = cur2->next;
if(tail == NULL)
{
result = node;
}
else
{
tail->next = node;
}
node->next = NULL;
tail = node;
}
}
return result;
}
== 上述内容均为学习过程总结,如有不足之处,请指正 ==