.h
# pragma once
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
typedef int DataType;
typedef struct Node
{
struct Node* _pNext;
DataType _data;
}Node, *PNode;
//不带头结点的单链表//
// .h
// 链表初始化
void SListInit(PNode* pHead);//需要改变外部实参的指向,所以传指针;否则,相当于值传递
// 尾插
void SListPushBack(PNode* pHead, DataType data);
// 尾删
void SListPopBack(PNode* pHead);
// 头插
void SListPushFront(PNode* pHead, DataType data);
// 头删
void SListPopFront(PNode* pHead);
查找值为data的结点,返回该结点在链表中的位置
PNode SListFind(PNode pHead, DataType data);
//
// 任意位置的插入,在链表pos位置后插入结点data
void SListInsert(PNode* pHead, PNode pos, DataType data);
//任意位置的删除, 删除链表pos位置上的结点
void SListErase(PNode* pHead, PNode pos);
//
销毁单链表
void SListDestroy(PNode* pHead);
//
求链表中结点的个数
int SListSize(PNode pHead);
//
将链表中的结点清空
void SListClear(PNode* pHead);
//
// 获取结点
PNode BuySListNode(DataType data);
//
获取链表中的最后一个结点,返回该结点的地址
//PNode SListBack(PNode pHead);
//打印单链表
void PrintList(PNode *pHead);
///
//从尾到头打印单链表
void PrintListFromTail2Head(PNode pHead);
// 删除链表的非尾结点,要求不能遍历链表 (删除后一个节点,替换到要删除的位置)
void DeleteNotTailNode(PNode pos);
// 在链表pos位置前插入值为data的结点 (插入新节点,后交换前一个节点与新节点)
void InsertPosFront(PNode pos, DataType data);
// 用单链表模拟实现约瑟夫环
// 约瑟夫环 (1.报数 2、删除节点)
void JosephCircle(PNode* pHead, const int M);
//找尾节点(找链表中最后一个节点的位置)
PNode slistBack(PNode pHead);
// 使用冒泡方式对单链表进行排序
void BubbleSort(PNode pHead);
// 单链表的逆序---三个指针
//直接在该链表中插入需要O(n^2);借助一个链表需要O(n),所以用三个指针
void ReverseSList(PNode* pHead);
// 单链表的逆序---使用头插法
PNode ReverseSListOP(PNode pHead);
// 合并两个有序链表,合并起来依然要有序
PNode MergeSList(PNode pHead1, PNode pHead2);
// 查找链表的中间结点,要求只能遍历一次链表
PNode FindMiddleNode(PNode pHead);
// 查找链表的倒数第K个结点 (一个指针先走k步后,两个指针一起走:
//1、k>链表中的节点个数:NULL
//2、k<=链表中的节点个数:pSLow,pFast
PNode FindLastKNode(PNode pHead, int K);
// 删除链表的倒数第K个结点,要求只能遍历链表一次
PNode DeleteLastKNode(PNode pHead, int K);
// 判断两个单链表是否相交---链表不带环
//1、第一个链表的最后一个节点指向第二个链表的最后一个节点
//2、第一个链表的最后一个节点指向第二个链表的任意一个节点
//3、第一个链表的最后一个节点指向第二个链表的第一个节点
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2);
// 如果相交 获取交点
// 求不带环单链表相交交点
PNode GetCrossNode(PNode pHead1, PNode pHead2);
// 判断链表是否带环
PNode IsCircle(PNode pHead);
// 求环的长度
int GetCircleLen(PNode pHead);
// 求环的入口点--注意推断过程
PNode GetEnterNode(PNode pHead, PNode pMeetNode);
// 判断链表是否带环,链表可能带环
int IsListCrossWithCircle(PNode pHead1, PNode pHead2);
// 复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求
//复制这个链表,返回复制后的新链表
//1、在原链表每个节点后插入值相同的新节点
//2、给新节点插入节点的随机指针域赋值
//3、将插入的新节点从链表中拆下来
typedef struct CpmplexListNode{
struct CpmplexListNode *pNext;
struct CpmplexListNode *pRandom;//可以指向链表中的任意节点,也包括自己和空
DataType data;
}ComplexListNode,*pComplexListNode;
pComplexListNode CopyComplexList(pComplexListNode pHead);
.c
# define _CRE_SECURE_NO_WARNINGS 1
# include"Link.h"
void SListInit(PNode* pHead)
{
assert(pHead);
*pHead = NULL;
}
PNode BuySListNode(DataType data)
{
PNode pNewNode = (PNode)malloc(sizeof(Node));
if (pNewNode == NULL)
return NULL;
pNewNode->_pNext = NULL;
pNewNode->_data = data;
return pNewNode;
}
//尾插:
//1、空链表(链表已经存在,但是里面没有节点,直接插入)
//2、非空
//(1)一个节点
//(2)多个节点(一个节点记录当前位置pPre,一个节点向后走pCur
void SListPushBack(PNode* pHead, DataType data)//需要改变外部实参的指向,所以传指针;否则,相当于值传递
{
PNode pNewNode = NULL;
assert(pHead);//phead为空这种情况一定不存在,检测链表是否存在,若是pHead不合理(非法)会触发assert,导致程序崩溃
//if(NULL==pHead) return;pHead为空这种情况有可能存在,检测链表是否存在
pNewNode = BuySListNode(data);
if (NULL == *pHead)
{
*pHead = pNewNode;
}
else
{
PNode pCur = *pHead;
while (pCur->_pNext)
{
//pCur++必须应用于空间连续的情况
pCur = pCur->_pNext;
}
pCur->_pNext = pNewNode;
}
}
//尾删
//1、空链表,直接返回
//2、只有一个节点,直接删除,pHead置空
//3、多个节点,先找倒数第二个节点,倒数第二个节点的下一个节点为当前需要被删除的位置,置为空。
void SListPopBack(PNode* pHead, DataType data)
{
PNode pDelNode = *pHead;
assert(pHead);
if (NULL == *pHead)
return;
else if (NULL == (*pHead)->_pNext)//找到倒数第二个节点,再将倒数第一个节点置为空
{
//只有一个节点
free(*pHead);
*pHead = NULL;
}
else
{
PNode pCur = *pHead;
while (pCur->_pNext->_pNext)
{
pCur = pCur->_pNext;
}
free(pCur->_pNext);
pCur->_pNext = NULL;
}
}
//头插
//1、空链表
//2、非空:(1)新节点链接链表(新节点的下一个位置指向头指针)
//(2)头指针指向新节点
void SListPushFront(PNode* pHead, DataType data)
{
PNode pNewNode = NULL;
assert(pHead);
pNewNode = BuySListNode(data);
if (NULL == pNewNode)
return;
pNewNode->_pNext = *pHead;
*pHead = pNewNode;
}
//头删
//1、空链表,直接返回
//2、只有一个节点,直接删除
//3、多个节点(1)保存第一个节点
//(2)改变指向
// (3)删除节点
void SListPopFront(PNode* pHead)
{
PNode pDelNode = NULL; //保存第一个节点
assert(pHead);
if (NULL == *pHead)
return;
pDelNode = *pHead;
*pHead = pDelNode->_pNext;//改变指向
free(pDelNode);//删除节点
}
//找当前节点
PNode SListFind(PNode pHead, DataType data)
{
PNode pCur = pHead;
while (pCur)
{
if (pCur->_data == data)
{
return pCur;
}
pCur = pCur->_pNext;
}
return NULL;
}
// 任意位置的插入,在链表pos位置后插入结点data
//1、查找pos节点的位置
//2、插入pos节点之后的位置
void SListInsert(PNode* pHead, PNode pos, DataType data)
{
PNode pNewNode = NULL;
assert(pHead);
if (NULL == *pHead || NULL == pos)//空链表或者不给定位置,则不能插入
return;
pNewNode = BuySListNode(data);
if (NULL == pNewNode)
return;
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
}
//任意位置的删除, 删除链表pos位置上的结点
//找pos的位置
//(1)pos在链表头部,头删
//(2)pos在其他位置,找到pos的前一个位置;
void SListErase(PNode* pHead, PNode pos)
{
assert(pHead);
if ((NULL == *pHead) || (NULL == pos))
return;
if (pos == *pHead)//pos在链表头部,头删
SListPopFront(pHead);
else
{
PNode pCur = *pHead;//pos在其他位置:找到pos的前一个位置;
while ((pCur) && (pCur->_pNext != pos))
{
pCur = pCur->_pNext;
if (pCur)
{
pCur->_pNext = pos->_pNext;
free(pos);
}
}
}
}
//将链表中的结点清空
//有节点先标记节点
//按头删的方法删除
void SListClear(PNode* pHead)
{
PNode pDelnode = NULL;
assert(pHead);
while (*pHead)
{
PNode pDelnode = *pHead;
*pHead = pDelnode->_pNext;
free(pDelnode);
}
}
//销毁单链表
void SListDestroy(PNode* pHead)
{
SListClear(pHead);
}
// 求链表中结点的个数
int SListSize(PNode pHead)
{
PNode pCur = NULL;
int count = 0;
pCur = pHead;
while (pCur)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
//打印链表
void PrintList(PNode pHead)//不需要改变外部指针的指向,所以用一级指针
{
PNode pCur = pHead;
while (pCur)
{
printf("%d->", pCur->_data);
pCur = pCur->_pNext;
}
printf("NULL\n");
}
//从尾到头打印单链表
void PrintListFromTail2Head(PNode pHead)
{
if (pHead)
{
PrintListFromTail2Head(pHead->_pNext);
printf("%d", pHead->_data);
}
}
//删除无头单链表的非尾结点,要求不能遍历链表 (删除后一个节点,替换到要删除的位置)
//删除pos后一个节点的信息,将后一个节点的值赋给前一个节点,因为不能遍历,所以不能直接删除
void DeleteNotTailNode(PNode pos)
{
PNode pDelNode = NULL;//保存要删除的位置
//PNode pDelNode = pos->_pNext;//这样会导致下一步检测pos是否存在没有意义
if (NULL == pos&&NULL == pos->_pNext)//判断是否存在要删除的位置,是否为尾节点
return;
pDelNode = pos->_pNext;
pos->_data = pDelNode->_data;//把要删除节点下一个节点数据交给前一个
pos->_pNext = pDelNode->_pNext;
free(pDelNode);//删除下一个节点
}
//在无头单链表的一个节点前插入一个节点(不能遍历链表):在链表pos位置前插入值为data的结点
//(插入新节点到pos节点的后面,后交换前一个节点与新节点),数据改变了,但地址未曾改变
//或插入后,直接将前一个节点的值给第二个节点
void InsertPosFront(PNode pos, DataType data)
{
PNode pNewNode = NULL;
if (NULL == pos)
return;
pNewNode = BuySListNode(pos->_data);
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
pos->_data = data;
}
// 实现约瑟夫环 (1.报数 2、删除节点)
//约瑟夫环指的是:一组数字形成一个环,设置数字m,
//每次读到的第m个数字被删除,循环读取
//1、给定一个约瑟夫环:一串数字组成一个循环
//2、(1)报数;(2)删除节点:方式1:保存pcur的前一个节点pre,让pre节点的next域指向pcur的next域,把pCur放到pcur的next位置上
// 方式2:把pCur下一个位置的值交给pCur,保存数据,删除下个节点,然后从pCur位置开始下次报数
//接环:next指向空
void JosephCircle(PNode* pHead, const int M)
{
PNode pCur = NULL;
PNode pDelNode = NULL;
assert(pHead);
if (NULL == *pHead)
return;
pCur = *pHead;
while (pCur != pCur->_pNext)
{
int count = M;
//报数
while (--count)
pCur = pCur->_pNext;
//删节点(替换法删除)
pDelNode = pCur->_pNext;//把pCur下一个位置的值交给pCur
pCur->_data = pDelNode->_data; //保存数据,
pCur->_pNext = pDelNode->_pNext;//删除下个节点,
free(pDelNode);
*pHead = pCur;
return *pHead;
}
}
//找尾节点(找链表中最后一个节点的位置)
PNode slistBack(PNode pHead)
{
PNode pCur = pHead;
if (NULL == pHead)
return;
while (pCur->_pNext)
{
pCur = pCur->_pNext;
}
return pCur;
}
// 使用冒泡方式对单链表进行排序
void BubbleSort(PNode pHead)
{
PNode pPreCur = NULL;
PNode pCur = NULL;
PNode pTail = NULL;
if (NULL == pHead || NULL == pHead->_pNext)//为空或者只有一个节点不用排序
return;
pPreCur = pHead;
pCur = pPreCur->_pNext;
int IsChange = 0;//检验是否已交换成为有序
while (pCur != pTail)//pTail位于空的位置上
{
if ((pPreCur->_data) > (pCur->_data))
{
int tmp = pPreCur->_data;
pPreCur->_data = pCur->_data;
pCur->_data = tmp;
IsChange = 1;
}
pPreCur = pCur;
pCur = pPreCur->_pNext;
}
if (!IsChange)
pTail = pPreCur;
}
// 单链表的逆置(交换第一个节点和倒数第一个;法1、倒数第二个和第二个……时间复杂度为n^2)
//法二、借助辅助空间遍历两次
//采用---三个指针:
void ReverseSList(PNode* pHead)//需要改变指向,传二级指针
{
PNode pPre = NULL, pCur = NULL, pNext = NULL;
assert(pHead);
if (NULL == *pHead || NULL == (*pHead)->_pNext)//一个节点或者空不用逆置
return;
pCur = *pHead;
while (pCur)
{
pNext = pCur->_pNext;
pCur->_pNext = pPre;
pPre = pCur;
pCur = pNext;
}
*pHead = pPre;
}
//逆置 头插法
//1、创建一个新链表,pNewNode指向新链表的头节点
//2、pCur的next域指向pNewNode
//3、pcur放到next的位置
PNode ReverseSListOP(PNode pHead)
{
PNode pNewHead = NULL;
PNode pCur = NULL;
PNode pNext = NULL;
if (NULL == pHead)
return;
pCur = pHead;
while (pCur)
{
pNext = pCur->_pNext;
pCur->_pNext = pNewHead;
pNewHead = pCur;//新链表里的第一个节点
pCur = pNext;
}
return pNewHead;
}
//这两个逆置的方法都解决不了代码环的问题,我们可以先将代码环解开,然后逆置,逆置后
//将代码环解开后置空的那个节点与原代码环中的节点连接
// 合并两个有序链表,合并起来依然要有序
//比较两个链表中节点的大小 ,将小的那个链表中的元素搬到新空间中
//将当前节点较小的那个链表中的节点向后移动一步,继续与另一个链表中的节点进行比较
//循环进行;采用尾插法
PNode MergeSList(PNode pHead1, PNode pHead2)
{
PNode pNewNode = NULL;
PNode pTailNode = NULL;
PNode PL1 = pHead1;
PNode PL2 = pHead2;
//if (NULL == pHead1)
// return pHead2;
//if (NULL == pHead2)
// return pHead1;
if (NULL == pHead1 || NULL == pHead2)
return pHead1 == NULL ? pHead2 : pHead1;
//两表都不为空
if (PL1->_data < PL2->_data)
{
pNewNode = PL1;
PL1 = PL1->_pNext;
}
else
{
pNewNode = PL2;
PL2 = PL2->_pNext;
}
pTailNode = pNewNode;//向新链表中尾插节点
while (PL1&&PL2)
{
if (PL1->_data < PL2->_data)
{
pTailNode->_pNext = PL1;
PL1 = PL1->_pNext;
}
else
{
pTailNode->_pNext = PL2;
PL2 = PL2->_pNext;
}
pTailNode = pTailNode->_pNext;//已经尾插了新节点,改变pTail指针的指向
}
if (PL1)//PL1不为空,还有节点,PL2走到了末尾,把PL2剩下的节点全部挂到后面
pTailNode->_pNext = PL1;
else
pTailNode->_pNext = PL2;
return pNewNode;
}
// 查找链表的中间结点,要求只能遍历一次链表(块慢指针)
//走的快的(pFast)走两步,走的慢的(pSlow)走一步
//若为奇数个节点,pFast走到空位置的前一个位置(pFast的next为空),pSlow为中间位置
//若为偶数个节点,pFast最终走到空的位置,pSlow为中间节点的位置(两个中间位置的后一个),
//走到倒数第二个位置处;;
//若需要两个中间位置的前一个,则给一个指针标记中间位置的前一个位置即可
//if(pFast==NULL) return pPre;
PNode FindMiddleNode(PNode pHead)
{
PNode pFast = pHead;
PNode pSLow = pHead;
while (pFast&&pFast->_pNext)
{
pFast = pFast->_pNext->_pNext;
pSLow = pSLow->_pNext;
}
return pSLow;
}
// 查找链表的倒数第K个结点,只能遍历一次链表。 (一个指针先走k步后,两个指针一起走:
//快的pFast先朝前走k步,
//k>链表中节点的个数:NULL
//k<=链表中节点的个数:pSlow
PNode FindLastKNode(PNode pHead, int K)
{
PNode pFast = pHead;
PNode pSlow = pHead;
if (NULL == pHead || K <= 0)
return NULL;
//让Fast先走k步
while (K--)
{
if (NULL == pFast)//k超过链表中节点的个数
return NULL;
pFast = pFast->_pNext;
}
//让Fast先走k-1步
//while (--k)
//{
// if (NULL == pFast->_pNext)//k超过链表中节点的个数
// return NULL;
// pFast = pFast->_pNext;
//}
//两个指针同时往后走,每次走一步
while (pFast)
{
pFast = pFast->_pNext;
pSlow = pSlow->_pNext;
}
return pSlow;
}
//删除倒数第k个节点:
//1、找倒数第k个节点
//2、删除节点(头节点,头删phead指向next;
//非头节点,保存pSlow的前一个节点,pPre指向pFast:用于非空尾节点)
// 判断两个单链表是否相交---链表不带环
//一、相交
//1、第一个链表的最后一个节点指向第二个链表的最后一个节点:最后一个节点是否相同
//2、第一个链表的最后一个节点指向第二个链表的任意一个节点:判断两个链表的最后一个节点是否相同
//3、第一个链表的最后一个节点指向第二个链表的第一个节点:最后一个节点是否相同
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2)
{
PNode pTail1 = pHead1;
PNode pTail2 = pHead2;
if (NULL == pHead1 || NULL == pHead2)
return 0;
//找第一个链表的最后一个节点
while (pTail1->_pNext)
{
pTail1 = pTail1->_pNext;
}
//找第二个链表的最后一个节点
while (pTail2->_pNext)
{
pTail2 = pTail2->_pNext;
}
return pTail1 == pTail2;
}
// 如果相交 获取交点
//链表L1与链表L2相交
//1、交点到两个链表的头部的节点数是相同的,同时向后走,则一定会相交
//2、交点到两个链表的头部的节点数是不同的,较长的链表先走(长链表-短链表)步
PNode GetCrossNode(PNode pHead1, PNode pHead2)
{
int size1 = 0;
int size2 = 0;
PNode pCur1 = pHead1, pCur2 = pHead2;
int gap = 0;
if (!IsCrossWithoutCircle(pHead1, pHead2))//不相交,则返回
return NULL;
//求两个链表中节点的个数
while (pCur1)//求pCur1的长度
{
size1++;
pCur1 = pCur1->_pNext;
}
while (pCur2)//求pCur2的长度
{
size2++;
pCur2 = pCur2->_pNext;
}
//让长的链表先朝后走差值步
gap = size1 - size2;
pCur1 = pHead1;
pCur2 = pHead2;
if (gap > 0)//第一个链表长
{
while (gap--)
{
pCur1 = pCur1->_pNext;
}
}
else//gap>0
{
while (gap++)
{
pCur2 = pCur2->_pNext;
}
}
while (pCur1 != pCur2)
{
pCur1 = pCur1->_pNext;
pCur2 = pCur2->_pNext;
}
return pCur1;//该位置位交点,否则不相交
}
//判断两个链表是否相交,若相交,求交点(假设链表可能带环)
// 判断链表是否带环 (0,6,9)//给定两个指针一个一次走一步,一个一次走两步,判断是否会相交
//一个走1步,一个走3步,若是只有两个节点则不会相遇(快指针和慢指针的差为节点的个数)
//快指针和慢指针的差不得等于节点的个数
PNode IsCircle(PNode pHead)
{
PNode pFast = pHead;
PNode pSlow = pHead;
while (pFast&&pFast->_pNext)
{
pFast = pFast->_pNext->_pNext;//pFast不得为空
pSlow = pSlow->_pNext;//pFast->_pNext不得为空
if (pFast == pSlow)
return pFast;//带环
}
return NULL;//不带环
}
// 若带环,求环的长度
int GetCircleLen(PNode pHead)
{
PNode pMeetNode = IsCircle(pHead);//判断有没有带环。IsCircle(pHead)返回的为相遇点
PNode pCur = pMeetNode;
int count = 1;//因为没有算pMeetNode位置的节点个数,所以count必须从1开始
if (NULL == pMeetNode)//链表没有带环
return 0;
while (pCur->_pNext != pMeetNode)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
// 求环的入口点--注意推断过程
//一个指针从起始点开始,另一个指针从相遇点开始,一次走一步,一定会在入口点相遇
//只要慢指针进环了,快指针可以在一圈之内追上慢指针
PNode GetEnterNode(PNode pHead, PNode pMeetNode)
{
PNode PM = pMeetNode;//从相遇点往后走
PNode PH = pHead;//从链表起始位置往后走
if (NULL == pHead || NULL == pMeetNode)//链表和入口点都不能为空
return NULL;
while (PH != PM)
{
PH = PH->_pNext;
PM = PM->_pNext;
}
return PM;
}
//判断两个链表是否相交,若相交,求交点(假设链表可能带环)
//不带环的相交,还可以构环找交点(交点为入口点):即一个链表尾节点的next域指向另一个节点的开头
int IsListCrossWithCircle(PNode pHead1, PNode pHead2)
{
PNode PMeetNode1 = NULL;
PNode PMeetNode2 = NULL;
if (NULL == pHead1 || NULL == pHead2)//避免空链表的存在
return 0;
PMeetNode1 = IsCircle(pHead1);
PMeetNode2 = IsCircle(pHead1);
//两个链表都不带环
if (NULL == PMeetNode1&&NULL == PMeetNode2)
//找两个链表的最后一个节点,检测是否是同一个节点
{
PNode pTail1 = pHead1;
PNode pTail2 = pHead2;
while (pTail1->_pNext)//空链表也不带环,但是两个都为空,是相等的
pTail1 = pTail1->_pNext;
while (pTail2->_pNext)
pTail2 = pTail2->_pNext;
if (pTail1 == pTail2)//相交
return 1;
}
//两个链表都带环
else if (PMeetNode1&&PMeetNode2)//两个相遇点都存在,两个链表均带环
{
//让一个相遇点绕环一周,看另外一个相遇点是否存在
PNode pCur = PMeetNode1;
do
{
if (pCur == PMeetNode2)
return 2;
pCur = pCur->_pNext;
} while (pCur != PMeetNode1);
//此过程采用while循环会导致少判断一个节点
}
return 0;//一个带环,一个不带环;不相交
}
// 复杂链表的复制
pComplexListNode CopyComplexList(pComplexListNode pHead)
{
pComplexListNode pOldNode = pHead;
pComplexListNode pNewNode = NULL;
pComplexListNode pNewHead = NULL;
if (NULL == pHead)
return NULL;
//在原链表每个节点后插入值与原链表相同的新节点
while (pOldNode)
{
pNewNode = (pComplexListNode)malloc(sizeof(ComplexListNode));
if (NULL == pNewNode)
return NULL;
pNewNode->data = pOldNode->data;
pNewNode->pNext = NULL;
pNewNode->pRandom = NULL;
pNewNode->pNext = pOldNode->pNext;//插入新节点
pOldNode->pNext = pNewNode;//断开原链表
pOldNode = pNewNode->pNext;//oldNode向后移动一步
}
//给新插入节点的随机指针域赋值
pOldNode = pHead;
while(pOldNode)
{
pNewNode = pOldNode->pNext;//新节点的位置
if (pOldNode->pRandom == NULL)
pNewNode->pRandom = NULL;
else
pNewNode->pRandom = pOldNode->pRandom->pNext;
pOldNode = pNewNode->pNext;
}
//拆开
pOldNode = pHead;
pNewHead = pOldNode->pNext;
while (pOldNode->pNext)//有节点就不会终止
{
pNewNode = pOldNode->pNext;//新节点
pOldNode->pNext = pNewNode->pNext;//old指向新节点的下一个位置,即断开了
pOldNode = pNewNode;//oldNode移动一步到newnode处
}
return pNewHead;
}
test.c
# include"Link.h"
# define _CRT_SECURE_NO_WARNING 1
void Test1()
{
PNode pHead;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 9);
SListPushBack(&pHead, 3);
PrintList(&pHead);
SListPopBack(&pHead);
SListPopBack(&pHead);
PrintList(&pHead);
}
void Test2()
{
PNode pHead;
SListInit(&pHead);
SListPushFront(&pHead, 2);
SListPushFront(&pHead, 8);
SListPushFront(&pHead, 9);
SListPushFront(&pHead, 0);
SListPushFront(&pHead, 4);
PrintList(&pHead);
SListPopFront(&pHead);
PrintList(&pHead);
SListPopFront(&pHead);
SListPopFront(&pHead);
SListPopFront(&pHead);
SListPopFront(&pHead);
PrintList(&pHead);
}
void Test3()
{
PNode pHead, pCur;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 9);
SListPushBack(&pHead, 3);
PrintList(pHead);
pCur = SListFind(&pHead, 7);
if (pCur)
{
SListInsert(&pHead, pCur, 0);
}
SListErase(&pHead, pCur);
PrintList(pHead);
printf("size=%d\n", SListSize(pHead));
SListClear(&pHead);
SListClear(&pHead);
SListDestroy(&pHead);
}
//测试约瑟夫环
void Test4()
{
PNode pHead, pCur;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 6);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 8);
PrintList(pHead);
//建立环
slistBack(pHead)->_pNext = pHead;
JosephCircle(pHead, 5);
//解环
pHead->_pNext = NULL;
}
void TestBubbleSort()
{
PNode pHead, pCur;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 9);
SListPushBack(&pHead, 3);
PrintList(pHead);
BubbleSort(pHead);
PrintList(pHead);
SListDestroy(&pHead);
}
void TestReverseList()
{
PNode pHead;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 6);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 8);
PrintList(pHead);
ReverseSList(&pHead);
PrintList(pHead);
}
void TestReverseListOp()
{
PNode pHead;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 6);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 8);
PrintList(pHead);
pHead = ReverseSListOP(pHead);
PrintList(pHead);
}
void TestMergeList()
{
PNode pHead1,pHead2;
SListInit(&pHead1);
SListPushBack(&pHead1, 1);
SListPushBack(&pHead1, 2);
SListPushBack(&pHead1, 3);
SListPushBack(&pHead1, 4);
PrintList(pHead1);
SListInit(&pHead2);
SListPushBack(&pHead2, 3);
SListPushBack(&pHead2, 4);
SListPushBack(&pHead2, 6);
SListPushBack(&pHead2, 8);
PrintList(pHead2);
pHead1=MergeSList(pHead1, pHead2);
PrintList(pHead1);
SListDestroy(&pHead1);
}
void TestFindMiddleAndLastKNode()
{
PNode pHead,pCur=NULL;
PNode Cur = NULL;
SListInit(&pHead);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPushBack(&pHead, 5);
SListPushBack(&pHead, 6);
SListPushBack(&pHead, 7);
SListPushBack(&pHead, 8);
PrintList(pHead);
pCur =FindMiddleNode(pHead);
printf("中间节点是:%d\n", pCur->_data);
SListPopBack(&pHead);
PrintList(pHead);
pCur = FindMiddleNode(pHead);
printf("中间节点是:%d\n", pCur->_data);
Cur = FindLastKNode(pHead, 2);
if (Cur)
printf("链表中倒数第%d个节点是:%d\n", 2, Cur->_data);
else
printf("倒数第%d个节点不存在\n",2);
SListDestroy(&pHead);
}
void TestIsSlistCross()
{
//相交
//不相交
PNode pHead1=NULL, pHead2= NULL,pCur;
SListInit(&pHead1);
SListPushBack(&pHead1, 1);
SListPushBack(&pHead1, 2);
SListPushBack(&pHead1, 3);
SListPushBack(&pHead1, 4);
SListPushBack(&pHead1, 5);
SListPushBack(&pHead2, 6);
SListPushBack(&pHead2, 7);
SListPushBack(&pHead2, 8);
SListPushBack(&pHead2, 9);
SListPushBack(&pHead2, 0);
slistBack(pHead1)->_pNext = SListFind(pHead2, 7);
if (IsCrossWithoutCircle(pHead1, pHead2))
{
printf("两个链表相交\n");
pCur=GetCrossNode(pHead1, pHead2);
assert(pCur);
printf("交点为:%d\n", pCur->_data);
}
else
printf("两个链表不相交\n");
PrintList(pHead2);
}
void TestIsListCrossWithCircle()
{
PNode pHead1 = NULL, pHead2 = NULL, pCur;
SListPushBack(&pHead1, 1);
SListPushBack(&pHead1, 2);
SListPushBack(&pHead1, 3);
SListPushBack(&pHead1, 4);
SListPushBack(&pHead1, 5);
SListPushBack(&pHead1, 6);
SListPushBack(&pHead1, 7);
SListPushBack(&pHead1, 8);
slistBack(pHead1)->_pNext = SListFind(pHead1, 5);
SListPushBack(&pHead2, 1);
SListPushBack(&pHead2, 2);
SListPushBack(&pHead2, 3);
slistBack(pHead2)->_pNext = SListFind(pHead1, 3);
int ret = IsCrossWithoutCircle(pHead1, pHead2);
if (1 == ret)
{
printf("两个链表不带环相交\n");
}
else if (2 == ret)
{
printf("两个链表均带环相交\n");
}
else
printf("两个链表不相交\n");
}
void TestCopyComplexList()
{
ComplexListNode node1, node2, node3, node4;
pComplexListNode pHead = NULL;
node1.data = 1;
node1.pNext = &node2;
node1.pRandom = &node3;
node2.data = 2;
node2.pNext = &node3;
node2.pRandom = &node1;
node3.data = 3;
node3.pNext = &node4;
node3.pRandom = &node3;
node4.data = 4;
node4.pNext = NULL;
node4.pRandom = NULL;
pHead = CopyComplexList(&node1);
}
int main()
{
//Test1();
//Test2();
//Test3();
//Test4();
//TestBubbleSort();
//TestReverseList();
//TestReverseListOp();
//TestMergeList();
//TestFindMiddleAndLastKNode();
//TestIsSlistCross();
//TestIsListCrossWithCircle();
TestCopyComplexList();
system("pause");
return 0;
}