点击查看如何实现单链表以及单链表的一些基本操作函数
点击查看基于单链表经常见的面试题——基础篇
1.判断单链表是否带环?若带环,求环的长度?求环的入口点?
判断是否带环:
ListNode *IfRing(ListNode *list)//判断单链表是否带环,返回交点
{
ListNode* slow = list;
ListNode* fast = list;
//是否带环
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果相遇,则带环
{
return fast;
}
}
return NULL;
}
求环的长度,只需要让快慢指针再遍历一遍环,再次相遇就可以求出长度了
int LengthRing(ListNode *list)//环的长度
{
ListNode* fast = IfRing(list);
if (fast!=NULL)
{
int count = 1;
ListNode* slow = fast;
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果再相遇,则能求出长度
{
break;
}
count++;
}
return count;
}
else
{
return 0;
}
}
求环的入口点
ListNode *OepRing(ListNode *list)//环的入口点
{
ListNode *fast = IfRing(list);
if (fast != NULL)
{
ListNode *cur = list;
while (fast != cur)
{
fast = fast->next;
cur = cur->next;
}
return cur;
}
else
{
return NULL;
}
}
在这里我也直接写了一个一次性求出的封装函数
void IfLengOepRing(ListNode *list)
//判断单链表是否带环?若带环,求环的长度?
//求环的入口点?
{
assert(list);
ListNode* slow = list;
ListNode* fast = list;
//是否带环
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果相遇,则带环,求环的长度和入口点
{
printf("此链表带环\n");
//求环的长度
{
int count = 1;
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果再次相遇,跳出循环,输出循环多少次,也就是环的长度
{
printf("环的长度为%d\n",count);
break;
}
count++;
}
}
//环的入口点
{
ListNode *cur = list;
while (fast != cur)
{
fast = fast->next;
cur = cur->next;
}
printf("入口点为%d\n",cur->data);
}
break;
}
}
if ((fast==NULL)||(fast->next==NULL))//如果为空了,表示不带环
{
printf("此链表不带环\n");
}
}
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
ListNode *Intersect(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。(假设每个链表不带环)
{
//找到第一个链表的尾结点,
ListNode *cur = list;
ListNode *tail = list;
while (tail->next)
{
tail = tail->next;
}
//第一个链表的尾节点指向第二个链表的开始结点
tail->next = plist;
//判断是否相交(转换为是否带环问题)
ListNode*ret = IfRing(cur);
return ret;
}
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
ListNode *IntersectRing(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。
//(假设链表可能带环)【升级版】
{
ListNode* oep1 = OepRing(list);
ListNode* oep2 = OepRing(plist);
//两个链表都不带环(也就是上一题的解决方案)
if ((oep1 == NULL) && (oep2 == NULL))
{
return Intersect(list, plist);
}
//一个带环,一个不带环(不可能相交)
else if (((oep1 == NULL) && oep2) || ((oep2 == NULL) && oep1))
{
return NULL;
}
//两个都带环
else
{
//尾交(一个交点,一个入口点)
//若两个链表的入口点一样则只有一个交点(交点也是入口点)
//两链表各自环入口点已经求出,把list的环从入口点断开
//可以转换成求不带环的相交链表求交点
if (oep1 == oep2)
{
oep1->next = NULL;
return Intersect(list, plist);//交点
}
else
{
//环交
//环交会有两个入口点,从一个入口点出发遍历环
//遍历的过程中有结点等于另一个入口点,则表示环交,返回指向那个结点的指针(就是交点)
//有两个交点,交点也是入口点。
//否则,就是两个带环链表不相交
//在这里返回的是第二个链表的入口点
//也是第一个链表在第二个链表中的交点
ListNode* cur = oep1->next;
while (cur != oep1)
{
if (cur == oep2)
{
return oep1;
}
cur = cur->next;
}
/*//在这里返回的是第一个链表的入口点
//也是第二个链表在第一个链表中的交点
ListNode* cur = oep2->next;
while (cur != oep2)
{
if (cur == oep1)
{
return oep2;
}
cur = cur->next;
}*/
return NULL; //不相交
}
}
}
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
//ps: 复杂链表的结构
struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};
复制复杂链表思路:
1)第一步,把新创建的每个结点链接到原先结点的后面
void NewBackPrime(ComplexNode *list)
//第一步,把新创建的每个结点链接到原先结点的后面
{
ComplexNode *cur = list;
while (cur)
{
//每次新创建一个结点,让它指向原先结点指向的结点
//新创建结点的data和原先结点一样
ComplexNode *head = Init(cur->_data);
head->_next = cur->_next;
//新创建结点的指向的随机结点置空
head->_random = NULL;
//原先结点指向新创建的结点,这样整个链表就连到了一块
cur->_next = head;
//cur依次后移
cur = head->_next;
}
}
2)第二步,复制随机结点
void ComplexNodeRandom(ComplexNode *list)
//第二步,复制随机结点
{
ComplexNode *cur = list;
while (cur)
{
//找到插入的新结点
ComplexNode *head = cur->_next;
//让新结点指向的随机结点
//去指向
//原先结点指向随机结点的后一个
if (cur->_random)
{
head->_random = cur->_random->_next;
}
cur = head->_next;
}
}
3)第三步,让新创建链表的结点链接起来,原先链表的结点链接起来
ComplexNode *RemoveNewCode(ComplexNode *list)
//第三步,让新创建链表的结点链接起来,原先链表的结点链接起来
{
ComplexNode *cur = list;
ComplexNode *head = NULL;
ComplexNode *tmp = NULL;
if (cur)
{
head = tmp = cur->_next;
cur->_next = tmp->_next;
cur = cur->_next;
}
while (cur)
{
//让新创建链表的结点链接起来
tmp->_next = cur->_next;
tmp = tmp->_next;
//原先链表的结点链接起来
cur->_next = tmp->_next;
cur = cur->_next;
}
return head;
}
将这三步放到一块就是复杂链表的复制;
ComplexNode *ComplexList(ComplexNode *list)
//复杂链表的复制
{
NewBackPrime(list);
ComplexNodeRandom(list);
return RemoveNewCode(list);
}
同样,提供全部测试代码:
singlelinkedlist.h头文件
#ifndef __SINGLELINKEDLIST_H__
#include<stdio.h>
#include<windows.h>
#include<assert.h>
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct ListNode *next;
}ListNode;
typedef struct ComplexNode
{
int _data; // 数据
struct ComplexNode *_next; // 指向下一个节点的指针
struct ComplexNode *_random; // 指向随机节点(可以是链表中的任意节点 or 空)
}ComplexNode;
ListNode *InitList(DataType num);//初始化并赋值
void PushBack(ListNode **pplist, DataType num);//尾插
void PrintList(ListNode *plist);//输出
void PopBack(ListNode **pplist);//尾删
void PushFront(ListNode **pplist, DataType num);//头插
void PopFront(ListNode **pplist);//头删
ListNode *Find(ListNode *plist, DataType num);//查找
void Insert(ListNode** pplist, ListNode* pos, DataType x);//插入
void Erase(ListNode** pplist, ListNode* pos);//删除
void reverse(ListNode* pplist);//从尾到头打印链表
void DelHeadlessTail(ListNode* pos);//删除非尾结点
void InsertNotHeadNode(ListNode *pos, DataType num);//在一个节点前插入一个节点
void YueSeFu(ListNode *plist, DataType num);//约瑟夫环问题
void ReverseList(ListNode **pplist);//逆序单链表
void SortList(ListNode *plist);//冒泡排序
ListNode *MergeList(ListNode *list, ListNode *plist);//(尾插法)合并有序链表并输出有序
ListNode *MidNode(ListNode *list);//查找单链表的中间节点,要求只能遍历一次链表
ListNode *CountBackwards(ListNode *list, DataType num);//查找单链表的倒数第k个节点,要求只能遍历一次链表
ListNode *Ring(ListNode *list);//给链表带环
void IfLengOepRing(ListNode *list);//判断单链表是否带环?若带环,求环的长度?求环的入口点?
ListNode *IfRing(ListNode *list);//判断单链表是否带环,返回交点
int LengthRing(ListNode *list);//环的长度
ListNode *OepRing(ListNode *list);//环的入口点
ListNode *Intersect(ListNode *list, ListNode *plist);//判断两个链表是否相交,若相交,求交点。(假设每个链表不带环)
ListNode *IntersectRing(ListNode *list, ListNode *plist);//判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
ComplexNode *ComplexList(ComplexNode *list);//复杂链表的复制
ComplexNode *Init(DataType num);//定义一个新结构体链表结点
void NewBackPrime(ComplexNode *list);//第一步,把新创建的每个结点链接到原先结点的后面
void ComplexNodeRandom(ComplexNode *list);//第二步,复制随机结点
ComplexNode *RemoveNewCode(ComplexNode *list);//第三步,让新创建链表的结点链接起来,原先链表的结点链接起来
void PushBackComplex(ComplexNode **pplist, DataType num);//尾插,为了方便复制复杂链表使用
ComplexNode *FindComplex(ComplexNode *plist, DataType num);//查找
#endif//__SINGLELINKEDLIST_H__
singlelinkedlist.c实现部分
#include "singlelinkedlist.h"
ListNode *InitList(DataType num)//定义一个新的结点
{
ListNode *node = (ListNode*)malloc(sizeof(ListNode));
node->data = num;
node->next = NULL;
return node;
}
void PushBack(ListNode **pplist, DataType num)//尾插
{
if (*pplist == NULL)//空链表
{
*pplist = InitList(num);//定义一个结点
}
else if ((*pplist)->next == NULL)//只有一个结点
{
(*pplist)->next = InitList(num);
}
else//正常情况(多个结点)
{
ListNode *tail = *pplist;
while (tail->next)
{
tail = tail->next;//依次指向下一个结点,找到为空的尾结点
}
tail->next = InitList(num);//找到以后直接添加一个结点
}
}
void PrintList(ListNode *plist)//打印链表
{
ListNode *tail = plist;
while (tail)
{
printf("%d->", tail->data);
tail = tail->next;
}
printf("NULL");
printf("\n");
}
void PopBack(ListNode **pplist)//尾删
{
if (*pplist == NULL)//空链表
{
return;
}
else if ((*pplist)->next == NULL)//只有一个结点,直接释放
{
free(*pplist);
*pplist = NULL;
}
else
{
ListNode* tail = *pplist;
ListNode* pos = tail;
while (tail->next)//tail指向pos的后一个结点
{
pos = tail;
tail = tail->next;
}
free(tail);//释放最后一个结点就相当于删除了尾结点
tail = NULL;
pos->next = NULL;
}
}
void PushFront(ListNode **pplist, DataType num)//头插
{
if (*pplist == NULL)//空链表
{
*pplist = InitList(num);
}
else
{
ListNode *tmp = InitList(num);//开辟一个新的结点
tmp->next = *pplist;//让它指向原先的开始结点
*pplist = tmp;//pplist依然开始结点
}
}
void PopFront(ListNode **pplist)//头删
{
if (*pplist == NULL)//空链表
{
return;
}
else if ((*pplist)->next == NULL)//只有一个结点
{
*pplist = NULL;
}
else
{
ListNode *tmp = (*pplist)->next;//tmp指向原先头结点指向的下一个位置
free(*pplist);
*pplist = tmp;
}
}
ListNode *Find(ListNode *plist, DataType num)//查找
{
assert(plist);//断言其是否为空链表
while (plist)
{
if (plist->data == num)
{
return plist;
}
plist = plist->next;
}
return NULL;
}
void Insert(ListNode** pplist, ListNode* pos, DataType num)//插入
{
assert(*pplist&&pos);
if (((*pplist)->next == NULL) || (pos == *pplist))
//只有开始结点或者是要插入的正好在开始结点的前面
{
PushFront(pplist, num);
}
else
{
ListNode* tmp = NULL;
ListNode* tail = *pplist;
while (tail->next != pos)
{
tail = tail->next;
}
tmp = InitList(num);
tail->next = tmp;
tmp->next = pos;
}
}
void Erase(ListNode** pplist, ListNode* pos)//删除
{
assert(*pplist&&pos);
if (((*pplist)->next == NULL) || (*pplist == pos))
{
PopFront(pplist);
}
else
{
ListNode* tmp = *pplist;
while (tmp->next != pos)
{
tmp = tmp->next;
}
tmp->next = pos->next;
free(pos);
pos = NULL;
}
}
void reverse(ListNode* plist)
//要实现反过来输出链表,我们每访问到一个结点的时候
//先递归输出它后面的结点,再输出该结点自身
//问题:当链表非常长的时候,就会导致函数调用的层级很深
//从而有可能导致函数调用栈溢出。
{
if (NULL == plist)
{
printf("NULL");
return;
}
reverse(plist->next);
printf("<-%d", plist->data);
}
void DelHeadlessTail(ListNode *pos)//删除无头链表的非尾结点
//由于链表的单向性,我们只能知道一个结点所指向的下一个结点
//我们可以把问题想象成是此结点与后一个结点交换
//只要把两个结点的数据域交换,把结点指向后一个结点所指向的结点
{
assert(pos);
ListNode *ppos = pos->next;
pos->data = ppos->data;
pos->next = ppos->next;
free(ppos);
ppos = NULL;
}
void InsertNotHeadNode(ListNode *pos,DataType num)
//4.在无头单链表的一个节点前插入一个节点
//实现原理
//A->pcur->B->C.....
//A->pcur->new->B->C.....
//A->new->pcur->B->C.....
{
assert(pos);
ListNode *tmp = InitList(num);
ListNode *ppos = pos; //记住原来节点的位置
tmp->next = pos->next;
pos->next = tmp;
tmp->data = pos->data;
pos->data = num;
}
void YueSeFu(ListNode *plist, DataType num)//约瑟夫环问题,报数为num的人出局
{
assert(plist);
ListNode *cur = plist;
ListNode *tmp = plist;
if (plist->next == NULL)
{
return;
}
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = tmp;//环形链表
cur = plist;
while (cur->next != cur)//头不等于尾,也就是剩下1个人就终止循环
{
DataType n = num;
while (--n)
{
tmp = cur;
cur = cur->next;
}
tmp->next = cur->next;//删除cur也就是报数为num的人
printf("出局的为%d\n", cur->data);
free(cur);
cur = tmp->next;//头往后走,也就是下一个人开始报数
}
printf("剩下的是%d\n",cur->data);
}
void ReverseList(ListNode **pplist) //逆序单链表
{
ListNode *cur = *pplist;//cur当前结点
ListNode *prev = NULL;//前一个结点
ListNode *pnext = NULL;//后一个结点
if (NULL == *pplist || NULL == (*pplist)->next)
return;
while (cur)
{
pnext = cur->next;
cur->next = prev;
prev = cur;
cur = pnext;
}
*pplist = prev;
}
void SortList(ListNode *plist)//冒泡排序
{
if ((plist == NULL) || (plist->next == NULL))
{
return;
}
int exchange = 0;
ListNode *tail = NULL;
while (tail != plist->next)
{
ListNode *cur = plist;
ListNode *next = plist->next;
while (next != tail)
{
if (cur->data > next->data)
{
DataType num = cur->data;
cur->data = next->data;
next->data = num;
exchange = 1;
}
cur = cur->next;
next = next->next;
}
if (exchange == 0)//冒泡优化
{
break;
}
tail = cur;
}
}
ListNode *MergeList(ListNode *list, ListNode *plist)//合并有序链表并输出有序
{//归并法(尾插法)
if (list == NULL)//如果链表1为空,则直接返回链表2的头指针
{
return list;
}
else if (plist == NULL)//如果链表2为空,则直接返回链表1的头指针
{
return list;
}
else
{
//找出新链表的头结点
ListNode *head = NULL;
if (list->data < plist->data)
{
head = list;
list = list->next;
}
else
{
head = plist;
plist = plist->next;
}
//尾插
ListNode *tail = head;
while (list && plist)
{
if (list->data < plist->data)
{
tail->next = list;
list = list->next;
}
else
{
tail->next = plist;
plist = plist->next;
}
tail = tail->next;
}
if (list)//循环结束,一个链表为空,头指针直接指向非空链表的开始结点
{
tail->next = list;
}
else
{
tail->next = plist;
}
return head;
}
}
ListNode *MidNode(ListNode *list)//查找单链表的中间节点,要求只能遍历一次链表
{
//链表个数为偶数时,输出中间两个结点的后一个,也就是slow
//当面试官说把两个中间值都输出来,那就把Slow和slow,这里用大写区分
//要输出中间值的第一个,那就更改循环条件为fast&&fast->next->next
ListNode *slow = list;
//ListNode *Slow = list;
ListNode *fast = list;
while (fast&&fast->next)//while (fast&&fast->next->next)
//要注意边界问题
{
//Slow = slow; //Slow比slow后一个位置
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
ListNode *CountBackwards(ListNode *list, DataType num)
//查找单链表的倒数第k个节点,要求只能遍历一次链表
{
ListNode *slow = list;
ListNode *fast = list;
while (--num)
{
fast = fast->next;
if (fast == NULL)
{
return NULL;
}
}
while (fast->next)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
ListNode *Ring(ListNode *list)//给链表带环
{
ListNode *cur = list;
ListNode *tail = list;
//找到尾结点
while (tail->next)
{
tail = tail->next;
}
//找到中间节点
ListNode*mid = MidNode(cur);
//带环,返回头指针
tail->next = mid;
return list;
}
void IfLengOepRing(ListNode *list)
//判断单链表是否带环?若带环,求环的长度?
//求环的入口点?
{
assert(list);
ListNode* slow = list;
ListNode* fast = list;
//是否带环
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果相遇,则带环,求环的长度和入口点
{
printf("此链表带环\n");
//求环的长度
{
int count = 1;
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果再次相遇,跳出循环,输出循环多少次,也就是环的长度
{
printf("环的长度为%d\n",count);
break;
}
count++;
}
}
//环的入口点
{
ListNode *cur = list;
while (fast != cur)
{
fast = fast->next;
cur = cur->next;
}
printf("入口点为%d\n",cur->data);
}
break;
}
}
if ((fast==NULL)||(fast->next==NULL))//如果为空了,表示不带环
{
printf("此链表不带环\n");
}
}
ListNode *IfRing(ListNode *list)//判断单链表是否带环,返回相遇的那个点
{
ListNode* slow = list;
ListNode* fast = list;
//是否带环
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果相遇,则带环
{
return fast;
}
}
return NULL;
}
int LengthRing(ListNode *list)//环的长度
{
ListNode* fast = IfRing(list);
if (fast!=NULL)
{
int count = 1;
ListNode* slow = fast;
while (fast&&fast->next)//注意边界问题
{
slow = slow->next;
fast = fast->next->next;
if (fast == slow)//如果再相遇,则能求出长度
{
break;
}
count++;
}
return count;
}
else
{
return 0;
}
}
ListNode *OepRing(ListNode *list)//环的入口点
{
ListNode *fast = IfRing(list);
if (fast != NULL)
{
ListNode *cur = list;
while (fast != cur)
{
fast = fast->next;
cur = cur->next;
}
return cur;
}
else
{
return NULL;
}
}
ListNode *Intersect(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。(假设每个链表不带环)
{
//找到第一个链表的尾结点,
ListNode *cur = list;
ListNode *tail = list;
while (tail->next)
{
tail = tail->next;
}
//第一个链表的尾节点指向第二个链表的开始结点
tail->next = plist;
//判断是否相交(转换为是否带环问题)
return OepRing(cur);
}
ListNode *IntersectRing(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。
//(假设链表可能带环)【升级版】
{
ListNode* oep1 = OepRing(list);
ListNode* oep2 = OepRing(plist);
//两个链表都不带环(也就是上一题的解决方案)
if ((oep1 == NULL) && (oep2 == NULL))
{
return Intersect(list, plist);
}
//一个带环,一个不带环(不可能相交)
else if (((oep1 == NULL) && oep2) || ((oep2 == NULL) && oep1))
{
return NULL;
}
//两个都带环
else
{
//尾交(一个交点,一个入口点)
//两个链表的入口点一样,只有一个交点
//两链表各自环入口点已经求出,把list的环从入口点断开
//可以转换成求不带环的相交链表求交点
if (oep1 == oep2)
{
oep1->next = NULL;
return Intersect(list, plist);//交点
}
else
{
//环交
//环交会有两个入口点,从一个入口点出发遍历环
//遍历的过程中有结点等于另一个入口点,则表示环交,返回指向那个结点的指针(就是交点)
//有两个交点,交点也是入口点。
//否则,就是两个带环链表不相交
//在这里返回的是第二个链表的入口点
//也是第一个链表在第二个链表中的交点
ListNode* cur = oep1->next;
while (cur != oep1)
{
if (cur == oep2)
{
return oep1;
}
cur = cur->next;
}
/*//在这里返回的是第一个链表的入口点
//也是第二个链表在第一个链表中的交点
ListNode* cur = oep2->next;
while (cur != oep2)
{
if (cur == oep1)
{
return oep2;
}
cur = cur->next;
}*/
return NULL; //不相交
}
}
}
ComplexNode *Init(DataType num)//定义一个新结构体链表结点
{
ComplexNode *node = (ComplexNode*)malloc(sizeof(ComplexNode));
node->_data = num;
node->_next = NULL;
node->_random = NULL;
return node;
}
void NewBackPrime(ComplexNode *list)
//第一步,把新创建的每个结点链接到原先结点的后面
{
ComplexNode *cur = list;
while (cur)
{
//每次新创建一个结点,让它指向原先结点指向的结点
//新创建结点的data和原先结点一样
ComplexNode *head = Init(cur->_data);
head->_next = cur->_next;
//新创建结点的指向的随机结点置空
head->_random = NULL;
//原先结点指向新创建的结点,这样整个链表就连到了一块
cur->_next = head;
//cur依次后移
cur = head->_next;
}
}
void ComplexNodeRandom(ComplexNode *list)
//第二步,复制随机结点
{
ComplexNode *cur = list;
while (cur)
{
//找到插入的新结点
ComplexNode *head = cur->_next;
//让新结点指向的随机结点
//去指向
//原先结点指向随机结点的后一个
if (cur->_random)
{
head->_random = cur->_random->_next;
}
cur = head->_next;
}
}
ComplexNode *RemoveNewCode(ComplexNode *list)
//第三步,让新创建链表的结点链接起来,原先链表的结点链接起来
{
ComplexNode *cur = list;
ComplexNode *head = NULL;
ComplexNode *tmp = NULL;
if (cur)
{
head = tmp = cur->_next;
cur->_next = tmp->_next;
cur = cur->_next;
}
while (cur)
{
//让新创建链表的结点链接起来
tmp->_next = cur->_next;
tmp = tmp->_next;
//原先链表的结点链接起来
cur->_next = tmp->_next;
cur = cur->_next;
}
return head;
}
ComplexNode *ComplexList(ComplexNode *list)
//复杂链表的复制
{
NewBackPrime(list);
ComplexNodeRandom(list);
return RemoveNewCode(list);
}
void PushBackComplex(ComplexNode **pplist, DataType num)//尾插,为了方便复制复杂链表使用
{
if (*pplist == NULL)//空链表
{
*pplist = Init(num);//定义一个结点
}
else if ((*pplist)->_next == NULL)//只有一个结点
{
(*pplist)->_next = Init(num);
}
else//正常情况(多个结点)
{
ComplexNode *tail = *pplist;
while (tail->_next)
{
tail = tail->_next;//依次指向下一个结点,找到为空的尾结点
}
tail->_next = Init(num);//找到以后直接添加一个结点
}
}
ComplexNode *FindComplex(ComplexNode *plist, DataType num)//查找
{
assert(plist);//断言其是否为空链表
while (plist)
{
if (plist->_data == num)
{
return plist;
}
plist = plist->_next;
}
return NULL;
}
test.c测试部分
#include "singlelinkedlist.h"
void test()
{
ListNode *list = NULL;
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PrintList(list);
PopBack(&list);
PrintList(list);
PopBack(&list);
PrintList(list);
PopBack(&list);
PrintList(list);
PopBack(&list);
PrintList(list);
}
void test1()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PrintList(list);
PopFront(&list);
PrintList(list);
PopFront(&list);
PrintList(list);
PopFront(&list);
PrintList(list);
PopFront(&list);
PrintList(list);
PopFront(&list);
PrintList(list);
}
void test2()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 4);
PushFront(&list, 5);
PushFront(&list, 6);
PrintList(list);
ListNode *ret = Find(list, 2);
//测试使用
/*if (ret != NULL)
{
printf("%p\n", ret);
}
else
{
printf("没有这个值!\n");
}*/
Insert(&list, ret, 3);
PrintList(list);
Erase(&list, ret);
PrintList(list);
}
void test3()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PrintList(list);
reverse(list);//从尾到头打印链表
printf("\n");
}
void test4()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PrintList(list);
ListNode *ret = Find(list, 2);
DelHeadlessTail(ret);//删除非尾结点
PrintList(list);
}
void test5()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 4);
PushFront(&list, 5);
PushFront(&list, 6);
PrintList(list);
ListNode *ret = Find(list, 2);
InsertNotHeadNode(ret, 3);//在一个节点前插入一个节点
PrintList(list);
YueSeFu(list, 2);//约瑟夫环问题
}
void test6()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PrintList(list);
ReverseList(&list);//单链表的逆置
PrintList(list);
}
void test7()
{
ListNode *list = NULL;
PushFront(&list, 3);
PushFront(&list, 2);
PushFront(&list, 5);
PushFront(&list, 4);
PushFront(&list, 8);
PrintList(list);
SortList(list);//冒泡排序
PrintList(list);
}
void test8()
{
ListNode *tmp = NULL;
PushFront(&tmp, 5);
PushFront(&tmp, 3);
PushFront(&tmp, 1);
PrintList(tmp);
ListNode *num = NULL;
PushFront(&num, 6);
PushFront(&num, 4);
PushFront(&num, 2);
PrintList(num);
//ListNode *ret = MergeList(tmp, num);//尾插法
//PrintList(ret);
}
void test9()
{
ListNode *list = NULL;
//PushFront(&list, 3);
//PushFront(&list, 2);
//PushFront(&list, 5);
//PushFront(&list, 4);
//PushFront(&list, 8);
//ListNode *ret = MidNode(list);//查找单链表的中间节点,要求只能遍历一次链表
//printf("%d\n",ret->data);//链表个数如果是奇数个,输出中间那个
PushFront(&list, 3);
PushFront(&list, 2);
PushFront(&list, 4);
PushFront(&list, 8);
ListNode *Ret = MidNode(list);//查找单链表的中间节点,要求只能遍历一次链表
printf("%d\n", Ret->data);//链表个数如果是偶数个,输出中间两个结点的后一个
}
void test10()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PrintList(list);
ListNode *ret = CountBackwards(list, 2);
printf("%d\n",ret->data);
}
void test11()
{
ListNode *list = NULL;
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 7);
PushFront(&list, 8);
PushFront(&list, 9);
PushFront(&list, 10);
PushFront(&list, 11);
PrintList(list);
ListNode *ret = Ring(list);//给链表带环
//IfLengOepRing(ret);//判断单链表是否带环?若带环,求环的长度?求环的入口点
/*ListNode* Ret = IfRing(ret);//判断单链表是否带环
if (Ret)
{
printf("该链表带环\n");
}
else
{
printf("该链表不带环\n");
}*/
//printf("环的长度为:%d\n", LengthRing(ret));//环的长度
ListNode *Ret = OepRing(ret);//环的入口点
if (Ret)
{
printf("环的入口点为:%d\n",Ret->data);
}
else
{
printf("该链表没有环\n");
}
}
void test12()
{
ListNode *list = NULL;
PushFront(&list, 8);
PushFront(&list, 7);
PushFront(&list, 6);
PushFront(&list, 5);
PushFront(&list, 4);
PushFront(&list, 3);
PushFront(&list, 2);
PushFront(&list, 1);
PrintList(list);
ListNode *plist = NULL;
PushFront(&plist, 5);
PushFront(&plist, 4);
PushFront(&plist, 3);
PushFront(&plist, 2);
PrintList(plist);
//Find(plist, 5)->next = Find(list, 6);//让两个链表相交
ListNode *ret = Intersect(list, plist);//判断两个链表是否相交,若相交,求交点。(假设链表不带环)
if (ret)
{
printf("两个链表相交,交点为:%d\n", ret->data);
}
else
{
printf("两个链表不相交\n");
}
}
void test13()
{
ListNode *list = NULL;
PushFront(&list, 4);
PushFront(&list, 3);
PushFront(&list, 2);
PushFront(&list, 1);
ListNode *ret = Ring(list);//给链表带环
ListNode *plist = NULL;
PushFront(&plist, 4);
PushFront(&plist, 3);
PushFront(&plist, 2);
PushFront(&plist, 1);
ListNode *Ret = Ring(plist);//给链表带环
//Find(plist, 3)->next = Find(list, 3);//让两个链表尾交
//Find(plist, 4)->next = Find(list, 3);//让两个链表环交
ListNode *oep = IntersectRing(ret, Ret);//判断两个链表是否相交,若相交,求交点。(假设链表可能带环)
if (oep != NULL)
{
printf("交点为:%d\n",oep->data);
}
else
{
printf("无交点\n");
}
}
void test14()
{
ComplexNode *list = NULL;
PushBackComplex(&list, 4);
PushBackComplex(&list, 3);
PushBackComplex(&list, 2);
PushBackComplex(&list, 1);
FindComplex(list, 1)->_random = FindComplex(list, 3);
FindComplex(list, 2)->_random = FindComplex(list, 4);
FindComplex(list, 3)->_random = NULL;
FindComplex(list, 4)->_random = NULL;
ComplexNode *plist = ComplexList(list);
}
int main()
{
//test();
//test1();
//test2();
//test3();
//test4();
//test5();
//test6();
//test7();
//test8();
//test9();
//test10();
//test11();
//test12();
//test13();
test14();
system("pause");
return 0;
}