1、List.h
#define _CRT_SECURE_NO_WARNINGS 1
#define __CONTACT_H__
#ifdef __CONTACT_H__
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* pNext;
int Length;
}Node, *pNode;
void InitSeqList(pNode *pHead);//初始化
void Pushback(pNode *pHead, DataType data);//尾插法
pNode BuyBode(DataType data);//创建第一个新节点
void popback(pNode *pHead);//尾删法
void pushfront(pNode *pHead, DataType data);//头插法
void popfront(pNode *pHead);//头删法
void insert(pNode pos, DataType data);//随机位置插入元素
void Erase(pNode *pHead, pNode pos);//删除任意位置的元素
pNode Find(pNode pHead, DataType data);//查找
void Remove(pNode *pHead, DataType data);//删除某个元素
void RemoveAll(pNode *pHead, DataType data);//删除所有相同的元素
int Empty(pNode pHead);//判空
void Clear(pNode *pHead);//清除
void Destroy(pNode *pHead);//销毁
int size(pNode pHead);//大小
void Bubblesort(PNode *pHead);//冒泡排序
void Selectsort(PNode *pHead);//选择排序
int BinarySearch(PNode *pHead,DataType data);//折半查找
void PrintSelectsort(pNode *pHead);//打印
///
void ReversePrintList(pNode pHead);
void DeleteNotailNode(pNode pos);
//void DeleteNotHeadNode(PNode pos);
void InsertNotHeadNode(pNode pos, DataType data);// 在无头单链表的一个非头节点前插入一个节点
//
pNode UniteList(pNode *pHead1, pNode *pHead2); //合并两个有序链表。
//PNode FindMidNode(PNode pHead); //寻找链表中间那个节点。
pNode FindLastKNode(pNode pHead, int k); //寻找倒数第k个节点。
//PNode ShowTailNode(PNode pHead); //露出尾部指针。
void JosephCircle(pNode pHead, int M); //单链表实现约瑟夫环(JosephCircle)
int IsCross(pNode pHead1, pNode pHead2); //判断两个链表是否相交,若相交,求交点。(假设链表不带环)
pNode GetCrossNode(pNode pHead1, pNode pHead2);//判断两个链表是否相交,若相交,求交点。(假设链表不带环)
pNode HasCircle(pNode pHead);// 判断单链表是否带环?返回快慢指针相遇的节点。为啥返回相遇的节点。
int GetCircleLen(pNode pMeetNode); //求环的长度。 参数是快慢指针相遇的节点。
pNode GetEnterNode(pNode pHead, pNode pMeetNode);//进环节点位置, 参数是快慢指针相遇的节点。
#endif
2、List.cpp
#include"List.hpp"
#include<iostream>
#include<assert.h>
using namespace std;
void InitSeqList(pNode *pHead)//链表初始化
{
assert(pHead);
*pHead = NULL;
}
int Empty(pNode pHead)//判段是否为空表
{
assert(pHead);
if (pHead)
return 1;
else
return 0;
}
int Size(pNode pHead)//链表有多少个节点
{
assert(pHead);
pNode pCurNode = pHead;
int count = 0;
while (pCurNode)
{
count++;
pCurNode = pCurNode->pNext;
}
return count;
}
pNode BuyBode(DataType data)//创建一个新节点
{
pNode pTemp = (pNode) malloc(sizeof(Node));
if (pTemp)
{
pTemp->data = data;
pTemp->pNext = NULL;
return pTemp;
}
else
{
cout << "开辟内存失败!" << endl;
return NULL;
}
}
void Pushback(pNode *pHead, DataType data)//尾插法
{
assert(pHead);
pNode pTailNode = *pHead;
if (*pHead == NULL)
{
*pHead = BuyBode(data);
}
else
{
while (pTailNode->pNext)
{
pTailNode = pTailNode->pNext;
}
pTailNode->pNext = BuyBode(data);
}
}
void popback(pNode *pHead)//尾删法
{
assert(pHead);
pNode pCurNode = *pHead;
pNode pReNode = NULL;
if (*pHead == NULL)//链表为空表
{
cout << "链表为空表!" << endl;
return;
}
else if (pCurNode->pNext == NULL)//只有一个节点
{
free(pCurNode);
*pHead = NULL;
}
else//有多个节点
{
while (pCurNode->pNext)
{
pReNode = pCurNode;
pCurNode = pCurNode->pNext;
}
free(pCurNode);
pReNode->pNext = NULL;
}
}
void pushfront(pNode *pHead, DataType data)//头插法
{
pNode pCurNode = NULL;
assert(pHead);
pCurNode = BuyBode(data);
pCurNode->pNext = *pHead;
*pHead = pCurNode;
}
void popfront(pNode *pHead)//头删法
{
pNode pCurNode = *pHead;
assert(pHead);
if (NULL == *pHead)//链表为空
{
cout << "链表为空,删除失败!" << endl;
return;
}
else//链表只有一个节点和链表有多个节点处理方式一样。
{
pNode pReNode = pCurNode->pNext;
*pHead = pReNode;
free(pCurNode);
}
}
pNode Find(pNode pHead, DataType data)
{
pNode pCur = NULL;
assert(pHead);
pCur = pHead;
while (pCur)
{
if (pCur->data == data)
return pCur;
pCur = pCur->pNext;
}
return NULL;
}
void Insert(pNode pHead,pNode pos, DataType data)//随机位置插入元素
{
assert(pHead);
pNode pTemp = Find(pHead, pos->data);//寻找插入位置,并返回这个位置。
pNode pTialNode = BuyBode(data);//插入节点。
if (pTemp)//扎到插入位置
{
pTialNode->pNext = pTemp->pNext;
pTemp->pNext = pTialNode;
}
else
{
cout << "没找到插入位置,插入失败!" << endl;
return;
}
}
void insert(pNode pos, DataType data)//随机位置插入元素
{
pNode pTialNode = BuyBode(data);//插入节点。
if (pos == NULL)
{
cout << "该节点不在链表中,插入失败!" << endl;
return;
}
pTialNode->pNext = pos->pNext;
pos->pNext = pTialNode;
}
void Erase(pNode *pHead, pNode pos)//删除任意位置的元素
{
pNode pCurNode = NULL;
assert(pHead);
assert(pos);
if (*pHead == NULL)
{
cout << "链表为空,删除失败!" << endl;
return;
}
else if (*pHead == pos)
{
free(*pHead);
*pHead = NULL;
}
else
{
pCurNode = *pHead;
while (pCurNode->pNext != pos)
{
pCurNode = pCurNode->pNext;
}
if (pCurNode != NULL)
{
pCurNode->pNext = pos->pNext;
free(pos);
}
}
}
void pRintList(pNode pHead)//打印单链表
{
pNode pCur = NULL;
if (NULL == pHead)
{
cout << "链表为空,不打印!" << endl;
}
pCur = pHead;
while (pCur)
{
cout << pCur->data << "->";
pCur = pCur->pNext;
}
cout << "NULL" << endl;
}
void Funtest1()
{
pNode pHead1;
InitSeqList(&pHead1);
//尾插
Pushback(&pHead1, 1);
Pushback(&pHead1, 2);
Pushback(&pHead1, 3);
cout << "尾插成功!" << endl;
pRintList(pHead1);
//尾删
popback(&pHead1);
cout << "尾删成功!" << endl;
pRintList(pHead1);
//头插
pushfront(&pHead1, 0);
pushfront(&pHead1, 1);
pushfront(&pHead1, 2);
cout << "头插成功!" << endl;
pRintList(pHead1);
//头删
popfront(&pHead1);
cout << "头删成功!" << endl;
pRintList(pHead1);
//任意位置插入
//第一种方法
Insert(pHead1, pHead1->pNext, 9);
pRintList(pHead1);
//第二种方法
insert(pHead1->pNext,4);
cout << "任意位置插入成功!" << endl;
pRintList(pHead1);
//任意位置删除
Erase(&pHead1,pHead1->pNext);
cout << "任意位置删除成功!" << endl;
pRintList(pHead1);
//查找某一个值得位置
pNode pTemp = Find(pHead1, 4);
cout << pTemp->data << endl;
}
void ReversePrintList(pNode pHead)//递归逆序打印单链表
{
if (pHead == NULL)
{
cout << "原链表为空,无法逆序!" << endl;
return;
}
else
{
if (pHead->pNext)
ReversePrintList(pHead->pNext);
cout << pHead->data<<"->";
}
}
pNode ReverseList(pNode pHead)//头插链表逆序
{
pNode pCurNode = pHead;
pNode pTialNode = pHead;
pNode pNewNode = NULL;
if (pHead == NULL && pHead->pNext == NULL)
{
return pHead;
}
else
{
while (pTialNode)
{
pTialNode = pCurNode->pNext;
pCurNode->pNext = pNewNode;
pNewNode = pCurNode;
pCurNode = pTialNode;
}
return pNewNode;
}
return NULL;
}
void DeleteNotTailNode(pNode pos)//删除一个无头单链表的非尾节点(不能遍历链表) 这个问题的解决方案是删除pos后面那个节点。
{
pNode pCurNode = NULL;
//assert(pos);
pCurNode = pos->pNext;//pCurNode指向pos后面的节点
pos->data = pCurNode->data;//pCurNode所指节点的值赋给pos节点
pos->pNext = pCurNode->pNext;//pos节点链接pCurNode的下一个节点
free(pCurNode);//删除要删除的节点
}
void InsertNotHeadNode(pNode pos, DataType data) //在无头单链表的一个非头节点前插入一个节点
{
assert(pos);
pNode pCurNode = NULL;
pCurNode = BuyBode(data);
if (pCurNode == NULL)
{
return;
}
else
{
pCurNode->pNext = pos->pNext;
pos->pNext = pCurNode;
pCurNode->data = pos->data;
pos->data = data;
}
}
void RemoveAll(pNode *pHead, DataType data)//删除某个元素
{
pNode pCurNode = NULL;
pNode pPreNode = NULL;
pNode pTemp = NULL;
assert(pHead);
if (*pHead == NULL)
{
cout << "链表为空,删除失败!" << endl;
return;
}
else
{
pCurNode = *pHead;
pPreNode = *pHead;
while (pCurNode->pNext)
{
if (pCurNode->data == data)
{
if (pCurNode == *pHead)//如果要删除的节点刚好是头节点,删除头节点
{
pTemp = pCurNode;
*pHead = pCurNode->pNext;
pCurNode = pCurNode->pNext;
free(pTemp);
}
else//要删除的不是头节点
{
pTemp = pCurNode;
pPreNode->pNext = pCurNode->pNext;
pCurNode = pCurNode->pNext;
free(pTemp);
}
}
pPreNode = pCurNode;
pCurNode = pCurNode->pNext;
}
if (pCurNode->data == data)
{
free(pCurNode);
pPreNode->pNext = NULL;
}
}
}
void Clear(pNode *pHead)//清除和销毁一样
{
assert(pHead);
pNode pCurNode = *pHead;
if (*pHead == NULL)
{
return;
}
else
{
while (pCurNode)
{
pNode pTemp = pCurNode;
pCurNode = pCurNode->pNext;
free(pTemp);
}
*pHead = NULL;
}
}
void Funtest2()
{
pNode pHead2;
InitSeqList(&pHead2);
Pushback(&pHead2, 2);
Pushback(&pHead2, 1);
Pushback(&pHead2, 2);
Pushback(&pHead2, 3);
Pushback(&pHead2, 2);
cout << "尾插成功!" << endl;
pRintList(pHead2);
//递归逆序打印单链表
//cout << "递归逆序打印:";
//ReversePrintList(pHead2);
//cout << "NULL" << endl;
//头插逆序打印单链表
/*cout << "头插逆序打印:";
pNode pNewNode = ReverseList(pHead2);
while (pNewNode)
{
cout << pNewNode->data<<"->";
pNewNode = pNewNode->pNext;
}
cout << "NULL" << endl;*/
//删除一个无头单链表的非尾节点
/*cout << "删除无头单链表的非尾节点:";
DeleteNotTailNode(pHead2->pNext);
pRintList(pHead2);*/
//删除所有元素值一样的节点
//RemoveAll(&pHead2, 2);
//pRintList(pHead2);
//链表大小
//cout << Size(pHead2) << endl;
//清除链表
//Clear(&pHead2);
//pRintList(pHead2);
//在无头单链表的一个非头节点前插入一个节点
InsertNotHeadNode(pHead2->pNext, 0);
pRintList(pHead2);
}
pNode MergeList(pNode pHead1, pNode pHead2) //合并两个有序链表。
{
pNode pNewNode = NULL;
if (pHead1 == NULL)
return pHead2;
else if (pHead2 == NULL)
return pHead1;
if (pHead1->data < pHead2->data)
{
pNewNode = pHead1;
pNewNode->pNext = MergeList(pHead1->pNext, pHead2);
}
else
{
pNewNode = pHead2;
pNewNode->pNext = MergeList(pHead1, pHead2->pNext);
}
return pNewNode;
}
void Funtest3()
{
pNode pHead3;
InitSeqList(&pHead3);
Pushback(&pHead3, 1);
Pushback(&pHead3, 3);
Pushback(&pHead3, 5);
cout << "尾插成功!" << endl;
pRintList(pHead3);
pNode pHead4;
InitSeqList(&pHead4);
Pushback(&pHead4, 2);
Pushback(&pHead4, 4);
Pushback(&pHead4, 6);
cout << "尾插成功!" << endl;
pRintList(pHead4);
//递归实现合并两个有序单链表
pNode pNewNode = MergeList(pHead3, pHead4);
while (pNewNode)
{
cout << pNewNode->data << "->";
pNewNode = pNewNode->pNext;
}
cout << "NULL" << endl;
}
pNode FindLastKNode(pNode pHead, int k)//寻找倒数第k个节点。
{
if (pHead == NULL || k==0)
return NULL;
pNode pFastNode = pHead;
pNode pSlowNode = NULL;
for (int idx = 0; idx < k - 1; ++idx)
{
if (pFastNode->pNext != NULL)
pFastNode = pFastNode->pNext;
else
return NULL;
}
pSlowNode = pHead;
while (pFastNode->pNext)
{
pFastNode = pFastNode->pNext;
pSlowNode = pSlowNode->pNext;
}
return pSlowNode;
}
void JosephCircle(pNode pHead, int M) //单链表实现约瑟夫环(JosephCircle)
{
int count = 0;
pNode pos = pHead;
pNode pTemp = NULL;
assert(pHead);
if (pHead == NULL || M < 0)
{
cout << "链表为空,或者出环人数无效!" << endl;
return;
}
while (pos->pNext)//单链表连成环
{
pos = pos->pNext;
}
pos->pNext = pHead;
while (pos != pos->pNext)//直到找到最后一个节点
{
count = M;
while (--count)//找到要被删除的节点,如果此处是count--那么就是每3位删除一个节点
{
pos = pos->pNext;
}
pTemp = pos->pNext;//保留要删除的节点
pos->pNext = pTemp->pNext;//被删除的节点的前一个节点指向删除节点的后一个节点
cout << "要删除的节点的是:" << pTemp->data << endl;
free(pTemp);
pTemp = NULL;
}
free(pos);
pos = NULL;
}
void FunTest4()
{
pNode pHead4;
InitSeqList(&pHead4);
/*for (int idx = 1; idx <= 10; idx++)
{
Pushback(&pHead4, idx);
}
pRintList(pHead4);*/
Pushback(&pHead4, 1);
//寻找倒数第K个节点
pNode pFindLastNode = FindLastKNode(pHead4, 1);
if (pFindLastNode)
cout << pFindLastNode->data << endl;
//单链表实现也约瑟夫环问题
//JosephCircle(pHead4, 2);
}
int IsCross(pNode pHead1, pNode pHead2) //判断两个链表是否相交(假设链表不带环)
{
pNode pCurNode = pHead1;
pNode pTurNode = pHead2;
if (pHead1 == NULL || pHead2 == NULL)
return 0;
while (pCurNode->pNext)
pCurNode = pCurNode->pNext;
while (pTurNode->pNext)
pTurNode = pTurNode->pNext;
if (pCurNode == pTurNode)//判断两个链表相交,就是判断尾节点是否一样。
return 1;
return 0;
}
pNode GetCrossNode(pNode pHead1, pNode pHead2)//判断两个链表是否相交,若相交,求交点。(假设链表不带环)
{
int count = 0;
if (pHead1 == NULL || pHead2 == NULL)
return NULL;
pNode pCurNode = pHead1;
pNode pTurNode = pHead2;
if (!IsCross(pHead1, pHead2))//两个链表不相交
return NULL;
//两个链表有交点
count = Size(pHead1) - Size(pHead2);
if (count > 0)
{
while (count--)
pCurNode = pCurNode->pNext;
}
if (count < 0)
{
count = -count;
while (count--)
pTurNode = pTurNode->pNext;
}
//两个链表到交点的距离相同
while (pCurNode != pTurNode)
{
pCurNode = pCurNode->pNext;
pTurNode = pTurNode->pNext;
}
return pCurNode;
}
pNode HasCircle(pNode pHead)// 判断单链表是否带环?返回快慢指针相遇的节点。
{
assert(pHead);
pNode pFastNode = pHead;
pNode pSlowNode = pHead;
while (pFastNode && pFastNode->pNext)
{
pFastNode = pFastNode->pNext->pNext;
pSlowNode = pSlowNode->pNext;
if (pFastNode == pSlowNode)
return pSlowNode;
}
return NULL;
}
int GetCircleLen(pNode pMeetNode)//求环的长度,参数是快慢指针相遇的节点。
{
int count = 1;
assert(pMeetNode);
pNode pCurNode = pMeetNode;
while (pCurNode->pNext != pMeetNode)
{
count++;
pCurNode = pCurNode->pNext;
}
return count;
}
pNode GetEnterNode(pNode pHead, pNode pMeetNode)//进环节点位置, 参数是快慢指针相遇的节点。
{
pNode pCurNode = pHead;
pNode pMeet = pMeetNode;
if (pHead == NULL || pMeetNode == NULL)
return NULL;
while (pCurNode != pMeet)
{
pCurNode = pCurNode->pNext;
pMeet = pMeet->pNext;
}
return pCurNode;
}
//复杂链表的复制。
//第一步:复制原始链表的任意节点N并创建新结点N',再把N'链接到N的后面
void CloneNode(ListNode* pHead)
{
ListNode* pCurNode = pHead;
while (pCurNode)
{
ListNode* pNewNode = new ListNode(0);
pNewNode->_value = pCurNode->_value;
pNewNode->Next = pCurNode->Next;
pNewNode->_random = NULL;
pCurNode->Next = pNewNode;
pCurNode = pNewNode->Next;
}
}
//第二步:设置复制出来节点的random,如果原始链表上的节点N的random指向S,则它对应的复制结点N'的random指向S的下一个S'
void ConnectSbioNode(ListNode* pHead)
{
ListNode* pCurNode = pHead;
while (pCurNode)
{
ListNode* pCloneNode = pCurNode->Next;
if (pCurNode->_random)
{
pCloneNode->_random = pCurNode->_random->Next;
}
pCurNode = pCloneNode->Next;
}
}
//第三步:奇数位上为原始链表,偶数为上为复制的链表
ListNode* ReconnectNode(ListNode* pHead)
{
if (NULL == pHead)
return NULL;
ListNode* pCurNode = pHead;
ListNode* pTempNode = NULL;
ListNode* pTempHead = NULL;
pTempHead = pTempNode = pCurNode->Next;
pCurNode->Next = pTempNode->Next;
pCurNode = pCurNode->Next;
while (pCurNode)
{
pTempNode->Next = pCurNode->Next;
pTempNode = pTempNode->Next;
pCurNode->Next = pTempNode->Next;
pCurNode = pCurNode->Next;
}
return pTempHead;
}
void FunTest5()
{
pNode pHead1;
InitSeqList(&pHead1);
Pushback(&pHead1, 1);
Pushback(&pHead1, 2);
Pushback(&pHead1, 3);
pRintList(pHead1);
pNode pHead2;
InitSeqList(&pHead2);
pushfront(&pHead2, 6);
pushfront(&pHead2, 5);
pushfront(&pHead2, 4);
pRintList(pHead2);
//判断两个链表是否相交
pHead1->pNext = pHead2->pNext->pNext;//两个链表连起来
//cout << "两个链表是否相交:"<<IsCross(pHead1,pHead2) << endl;
//找出两个链表相交的节点
pNode CrossNode = GetCrossNode(pHead1, pHead2);
if (NULL != CrossNode)
cout << "两个链表相交的节点是:" << CrossNode->data << endl;
else
cout << "链表无交点!" << endl;
//判断单链表成环
pNode pHead3;
InitSeqList(&pHead3);
for (int idx = 1; idx <= 10; idx++)
{
Pushback(&pHead3, idx);
}
pRintList(pHead3);
pNode pCur = pHead3;
while (pCur->pNext)//单链表连成环。
pCur = pCur->pNext;
pCur->pNext = pHead3->pNext;
pNode HasNode = HasCircle(pHead3);
if (HasNode)
cout << "链表带环,相遇点是:" << HasNode->data << endl;
else
cout << "链表不带环!" << endl;
//环的长度
int Count = GetCircleLen(HasNode);
cout << Count << endl;
//入环的节点
pNode EnterNode = GetEnterNode(pHead3, HasNode);
cout << EnterNode->data << endl;
}
int main()
{
//Funtest1();
//Funtest2();
//Funtest3();
//FunTest4();
FunTest5();
system("pause");
return 0;
}