.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; }