linklist.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <windows.h>
typedef int DataType;
typedef struct ListNode
{
struct ListNode* pNext;
DataType _data;
}Node,*pNode;
//初始化
void SlinkInit(pNode* ppHead);
//新建一个节点
pNode BuyListNode(DataType data);
//尾插一个节点
void SlinkPushBack(pNode* ppHead, DataType data);
//尾删
void SlinkDPopBack(pNode* ppHead);
//打印链表
void print(pNode pHead);
//头插
void SlinkPushfront(pNode * ppHead, DataType data);
//头删
void SlinkPopfront(pNode* ppHead);
//查找
pNode SListFind(pNode* ppHead, DataType data);
//任意位置插入
void SListDInsert(pNode* ppHead, pNode pos, DataType data);
//任意位置删除
void SListDErase(pNode* ppHead, pNode pos);
//在链表的一个节点前插入一个节点(不遍历)
void SListfront(pNode pos, DataType data);
//删除一个非尾节点
void SListEraseFW(pNode pos);
//计算链表的长度
int SListSixe(pNode pHead);
//判断链表是否为空
int SListEmpty(pNode pHead);
//清空链表
void SListDestory(pNode * ppHead);
//逆向打印
void rprint(pNode pHead);
//逆向销毁
void rDestory(pNode* ppHead);
//约瑟夫环
void JosephCircle(pNode* ppHead, size_t M);
//链表逆至
void ReverseList(pNode * ppHead);
//头插法逆置
void ReverseListD(pNode * ppHead);
//冒泡排序
void bubble_sort(pNode pHead);
//查找链表的中间节点
pNode FindMiddleNode(pNode pHead);
//查找倒数第K个节点
pNode FindLastKNode(pNode pHead, size_t K);
//删除倒数第K个节点
void DeleteLastKNode(pNode* ppHead,size_t K);
//合并两个有序的链表,然后链表依然有序
pNode MergeList(pNode pHead1, pNode pHead2);
//判断链表是否带环
pNode HasCircle(pNode pHead);
//带环链表的环的长度
size_t GetCircleLen(pNode pHead);
//求链表的入口点
pNode GetEnterNode(pNode pHead, pNode pMeetNode);
//两个链表是否相交(不带环)
int IsCrossWithout(pNode pHead1, pNode pHead2);
//两个链表相交入入口点(不带环)
pNode GetCrossNode(pNode pHead1, pNode phead2);
//两个链表是否相交(可能带环)
int IsCrossWithCircle(pNode pHead1, pNode pHead2);
//两个的交点可能带环
pNode GetCrossNodeWith(pNode pHead1, pNode pHead2);
linklist.c
#include "linklist.h"
//初始化
void SlinkInit(pNode* ppHead)
{
assert(ppHead);
*ppHead = NULL;
}
//新建一个节点
pNode BuyListNode(DataType data)
{
pNode pNewNode = (pNode)malloc(sizeof(Node));
if (NULL == pNewNode)
{
printf("申请节点失败!\n");
return NULL;
}
pNewNode->_data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
//尾插一个节点
void SlinkPushBack(pNode* ppHead, DataType data)
{
assert(ppHead);
pNode pCur = *ppHead;
if (*ppHead == NULL)
{
*ppHead = BuyListNode(data);
}
else
{
while (pCur->pNext)
{
pCur = pCur->pNext;
}
pCur->pNext = BuyListNode(data);
}
}
//尾删
void SlinkDPopBack(pNode* ppHead)
{
assert(ppHead);
pNode pCur = *ppHead;
pNode pPre = NULL;
if (*ppHead == NULL)
{
printf("链表为空,不能删除!!\n");
return;
}
else if ((*ppHead)->pNext == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
while (pCur->pNext)
{
pPre = pCur;
pCur = pCur->pNext;
}
free(pCur);
pPre->pNext = NULL;
}
}
//打印链表
void print(pNode pHead)
{
if (pHead == NULL)
{
printf("链表为空!!!\n");
return;
}
while (pHead)
{
printf("%d->", pHead->_data);
pHead = pHead->pNext;
}
printf("NULL\n");
}
//头插
void SlinkPushfront(pNode * ppHead, DataType data)
{
assert(ppHead);
pNode pCur = *ppHead;
if (*ppHead == NULL)
(*ppHead) = BuyListNode(data);
else
{
pCur = BuyListNode(data);
pCur->pNext = *ppHead;
*ppHead = pCur;
}
}
//头删
void SlinkPopfront(pNode* ppHead)
{
assert(ppHead);
if (NULL == *ppHead)
{
printf("链表为空,不能头删!!\n");
return;
}
else
{
pNode pDel = *ppHead;
*ppHead = (*ppHead)->pNext;
free(pDel);
}
}
//查找
pNode SListFind(pNode* ppHead, DataType data)
{
pNode pCur = NULL;
assert(ppHead);
if (NULL == *ppHead)
return NULL;
pCur = *ppHead;
while (pCur)
{
if (pCur->_data == data)
return pCur;
pCur = pCur->pNext;
}
return NULL;
}
//任意位置插入
void SListDInsert(pNode * ppHead, pNode pos, DataType data)
{
assert(ppHead);
if (NULL == *ppHead || NULL == pos)
return;
if (*ppHead == pos)
{
pNode pCur = BuyListNode(data);
pCur->pNext = *ppHead;
*ppHead = pCur;
}
else
{
pNode pPre = NULL;
pNode pCur = *ppHead;
while (pCur && pCur != pos)
{
pPre = pCur;
pCur = pCur->pNext;
}
if (pCur)
{
pNode pNew = BuyListNode(data);
pPre->pNext = pNew;
pNew->pNext = pCur;
}
}
}
//任意位置删除
void SListDErase(pNode* ppHead, pNode pos)
{
assert(ppHead);
if (NULL == *ppHead || NULL == pos)
return;
if (*ppHead == pos)
{
pNode pDel = *ppHead;
(*ppHead) = (*ppHead)->pNext;
free(pDel);
}
else
{
pNode pCur = *ppHead;
pNode pPre = NULL;
while (pCur && pCur != pos)
{
pPre = pCur;
pCur = pCur->pNext;
}
if (pCur)
{
pPre->pNext = pCur->pNext;
free(pCur);
}
}
}
//在链表的一个节点前插入一个节点(不遍历)
void SListfront(pNode pos, DataType data)
{
pNode pNewNode = NULL;
if (NULL == pos)
return;
pNewNode = BuyListNode(pos->_data);
pNewNode->pNext = pos->pNext;
pos->pNext = pNewNode;
pos->_data = data;
}
//删除一个非尾节点
void SListEraseFW(pNode pos)
{
pNode pDel = NULL;
if (NULL == pos || NULL == pos->pNext )
return;
pDel = pos->pNext;
pos->_data = pos->pNext->_data;
pos->pNext = pos->pNext->pNext;
free(pDel);
}
//计算链表的长度
int SListSixe(pNode pHead)
{
int count = 0;
if (NULL == pHead)
return 0;
while (pHead)
{
count++;
pHead = pHead->pNext;
}
return count;
}
//判断链表是否为空
int SListEmpty(pNode pHead)
{
return NULL == pHead;
}
//清空链表
void SListDestory(pNode * ppHead)
{
pNode pCur = NULL;
pNode pNext = NULL;
assert(ppHead);
if (NULL == *ppHead)
return;
else
{
pCur = *ppHead;
while (pCur)
{
pNext = pCur->pNext;
free(pCur);
pCur = pNext;
}
*ppHead = NULL;
}
}
//逆向打印
void rprint(pNode pHead)
{
if (NULL == pHead)
return;
if (pHead)
{
rprint(pHead->pNext);
printf("%d->", pHead->_data);
}
}
//逆向销毁
void rDestory(pNode* ppHead)
{
assert(ppHead);
if (*ppHead)
{
rDestory(&(*ppHead)->pNext);
free(*ppHead);
*ppHead = NULL;
}
}
//约瑟夫环
void JosephCircle(pNode* ppHead, size_t M)
{
pNode pCur = NULL;
assert(ppHead);
pCur = *ppHead;
if (NULL == pCur)
return;
while (pCur->pNext)
{
pCur = pCur->pNext;
}
pCur->pNext = *ppHead;
pCur = *ppHead;
pNode pDel = NULL;
while (pCur->pNext != pCur)
{
int n = M;
while (--n)
{
pCur = pCur->pNext;
}
pDel = pCur->pNext;
pCur->_data = pCur->pNext->_data;
pCur->pNext = pCur->pNext->pNext;
free(pDel);
}
pCur->pNext = NULL;
*ppHead = pCur;
}
//链表逆置三个指针
void ReverseList(pNode * ppHead)
{
pNode p1 = NULL;
pNode p2 = NULL;
pNode p3 = NULL;
assert(ppHead);
p2 = *ppHead;
while (p2)
{
p3 = p2->pNext;
p2->pNext = p1;
p1 = p2;
p2 = p3;
}
*ppHead = p1;
}
//头插法
void ReverseListD(pNode * ppHead)
{
pNode pCur = NULL;
pNode pNext = NULL;
pNode pNewNode = NULL;
assert(ppHead);
pCur = *ppHead;
while (pCur)
{
pNext = pCur->pNext;
pCur->pNext = pNewNode;
pNewNode = pCur;
pCur = pNext;
}
*ppHead = pNewNode;
}
void Swap(int *p, int *q)
{
int temp = *p;
*p = *q;
*q = temp;
}
//冒泡排序
void bubble_sort(pNode pHead)
{
pNode p1 = NULL;
pNode p2 = NULL;
int IsChange = 0;
if (NULL == pHead || NULL == pHead->pNext)
return;
while (p2 != pHead)
{
p1 = pHead;
while (p1 && p1->pNext && p1->pNext != p2)
{
if (p1->_data > p1->pNext->_data)
{
Swap(&p1->_data, &p1->pNext->_data);
IsChange = 1;
}
p1 = p1->pNext;
}
if (IsChange == 0)
return;
p2 = p1;
}
}
//查找链表的中间节点
pNode FindMiddleNode(pNode pHead)
{
pNode pFast = NULL;
pNode pSlow = NULL;
pNode pPre = NULL;
pFast = pHead;
pSlow = pHead;
while (pFast && pFast->pNext)
{
pPre = pSlow;
pSlow = pSlow->pNext; //如果是偶数个节点,man指针指向偏后的节点,如果想得到偏前的节点,
pFast = pFast->pNext->pNext; //pPre保存前一个节点
}
if (!pFast) //pFast为空说明偶数个节点,返回上一个
return pPre;
return pSlow;
}
//查找倒数第K个节点
pNode FindLastKNode(pNode pHead, size_t K)
{
pNode pFast = pHead;
pNode pSlow = pHead;
if (NULL == pHead || K == 0)
return NULL;
while (K--)
{
if (pFast == NULL)
{
printf("没有倒数第K个节点");
return NULL;
}
pFast = pFast->pNext;
}
while (pFast)
{
pFast = pFast->pNext;
pSlow = pSlow->pNext;
}
return pSlow;
}
//删除倒数第k个节点
void DeleteLastKNode(pNode* ppHead, size_t K)
{
pNode pFast = NULL;
pNode pSlow = NULL;
pNode pPre = NULL;
assert(ppHead);
pFast = *ppHead;
pSlow = *ppHead;
if (*ppHead == NULL || K == 0)
return;
while (K--)
{
if (pFast == NULL)
return;
pFast = pFast->pNext;
}
while (pFast)
{
pPre = pSlow;
pFast = pFast->pNext;
pSlow = pSlow->pNext;
}
pPre->pNext = pSlow->pNext;
free(pSlow);
}
//删除倒数第k个节点
#if 0
void DeleteLastKNode(pNode * ppHead, size_t k)
{
pNode pCur = FindLastKNode(*ppHead,k);
SListDErase(ppHead,pCur);
}
#endif
//合并两个有序的链表,然后链表依然有序
pNode MergeList(pNode pHead1, pNode pHead2)
{
pNode pTail = NULL;
pNode pNewNode = NULL;
if (NULL == pHead1 || NULL == pHead2)
return (pHead1) ? pHead1 : pHead2;
if (pHead1->_data > pHead2->_data)
{
pNewNode = pHead2;
pTail = pNewNode;
pHead2 = pHead2->pNext;
}
else
{
pNewNode = pHead1;
pTail = pNewNode;
pHead1 = pHead1->pNext;
}
while (pHead1 && pHead2)
{
if (pHead1->_data > pHead2->_data)
{
pTail->pNext = pHead2;
pHead2 = pHead2->pNext;
}
else
{
pTail->pNext = pHead1;
pHead1 = pHead1->pNext;
}
pTail = pTail->pNext;
}
if (pHead1 == NULL)
pTail->pNext = pHead2;
else
pTail->pNext = pHead1;
return pNewNode;
}
//判断链表是否带环
pNode HasCircle(pNode pHead)
{
pNode pFast = pHead;
pNode pSlow = pHead;
while (pFast && pFast->pNext)
{
pFast = pFast->pNext->pNext;
pSlow = pSlow->pNext;
if (pFast == pSlow)
return pFast;
}
return NULL;
}
//带环链表的环的长度
size_t GetCircleLen(pNode pHead)
{
pNode pMeetNode = HasCircle(pHead);
pNode pCur = pMeetNode;
size_t len = 1;
if (NULL == pMeetNode)
return 0;
while (pCur->pNext != pMeetNode)
{
len++;
pCur = pCur->pNext;
}
return len;
}
//求链表的入口点
pNode GetEnterNode(pNode pHead, pNode pMeetNode)
{
while (pHead != pMeetNode)
{
pHead = pHead->pNext;
pMeetNode = pMeetNode->pNext;
}
return pHead;
}
//个链表是否相交(不带环)
int IsCrossWithout(pNode pHead1, pNode pHead2)
{
if (NULL == pHead1 || NULL == pHead2)
return 0;
while (pHead1->pNext)
pHead1 = pHead1->pNext;
while (pHead2->pNext)
pHead2 = pHead2->pNext;
return pHead1 == pHead2;
}
//两个链表相交入入口点(不带环)
pNode GetCrossNode(pNode pHead1, pNode pHead2)
{
size_t size1 = 0;
size_t size2 = 0;
pNode pCur1 = pHead1;
pNode pCur2 = pHead2;
int div = 0;
if (NULL == pHead1 || NULL == pHead2)
return NULL;
if (!IsCrossWithout(pHead1, pHead2))
return NULL;
while (pCur1)
{
size1++;
pCur1 = pCur1->pNext;
}
while (pCur2)
{
size2++;
pCur2 = pCur2->pNext;
}
div = size1 - size2;
if (div > 0)
{
while (div--)
{
pHead1 = pHead1->pNext;
}
}
else
{
while (div++)
{
pHead2 = pHead2->pNext;
}
}
while (pHead1 != pHead2)
{
pHead1 = pHead1->pNext;
pHead2 = pHead2->pNext;
}
return pHead1;
}
//两个链表是否相交
int IsCrossWithCircle(pNode pHead1, pNode pHead2)
{
pNode pMeetNode1 = HasCircle(pHead1);
pNode pMeetNode2 = HasCircle(pHead2);
if (NULL == pMeetNode1 && NULL == pMeetNode2)
{
pNode pTailNode1 = pHead1;
pNode pTailNode2 = pHead2;
while (pTailNode1->pNext)
pTailNode1 = pTailNode1->pNext;
while (pTailNode2->pNext)
pTailNode2 = pTailNode2->pNext;
if (pTailNode1 == pTailNode2)
return 1;
}
else if (pMeetNode1 && pMeetNode2)
{
pNode pCur = pMeetNode1;
while (pCur->pNext != pMeetNode1)
{
if (pCur == pMeetNode2)
return 2;
pCur = pCur->pNext;
}
if (pCur == pMeetNode2)
return 2;
}
return 0;
}
//两个链表可能带环相交求交点
pNode GetCrossNodeWith(pNode pHead1, pNode pHead2)
{
int ret = IsCrossWithCircle(pHead1,pHead2);
if (ret == 1)
return GetCrossNode(pHead1,pHead2);
else if (ret == 2)
{
pNode pMeetNode1 = HasCircle(pHead1);
pNode pMeetNode2 = HasCircle(pHead2);
pNode pCur1 = GetEnterNode(pHead1, pMeetNode1);
pNode pCur2 = GetEnterNode(pHead2, pMeetNode2);
if (pCur1 == pCur2)
{
printf("环外相交\n");
return pCur1;
}
else
{
printf("环内相交!\n");
return pCur2;
}
}
return NULL;
}
test.c
#include "linklist.h"
void test();
void test1();
void test2();
void test3();
void test4();
void test5();//排序
void test6();
void test7();
void test8();
void test9();
void test10();
int main()
{
test10();
system("pause");
return 0;
}
//初始化、头插、头删、尾插、尾删
void test()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 2);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
print(pHead);
SlinkDPopBack(&pHead);
SlinkDPopBack(&pHead);
print(pHead);
SlinkPushfront(&pHead, 9);
SlinkPushfront(&pHead, 8);
SlinkPushfront(&pHead, 11);
print(pHead);
SlinkPopfront(&pHead);
print(pHead);
}
//任意位置插入元素,删除元素
void test1()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
SlinkPushBack(&pHead, 7);
print(pHead);
//在元链表值为三的节点插入一节点
pNode pp = SListFind(&pHead, 3);
SListDInsert(&pHead, pp, 80);
print(pHead);
pp = SListFind(&pHead, 4);
SListDErase(&pHead, pp);
print(pHead);
}
//
void test2()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 2);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
print(pHead);
pNode pCur = SListFind(&pHead, 3);
SListfront(pCur, 10);
print(pHead);
//删除一个非尾节点
pCur = SListFind(&pHead, 1);
SListEraseFW(pCur);
print(pHead);
rprint(pHead);
printf("链表的长度为:%d\n", SListSixe(pHead));
printf("链表是否为空%d\n", SListEmpty(pHead));
SListDestory(&pHead);
print(pHead);
}
//约瑟夫环
void test3()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 2);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
SlinkPushBack(&pHead, 5);
SlinkPushBack(&pHead, 6);
SlinkPushBack(&pHead, 7);
print(pHead);
JosephCircle(&pHead,3);
print(pHead);
}
//链表逆至
void test4()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 2);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
SlinkPushBack(&pHead, 5);
SlinkPushBack(&pHead, 6);
print(pHead);
ReverseListD(&pHead);
print(pHead);
}
//排序
void test5()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 5);
SlinkPushBack(&pHead, 4);
SlinkPushBack(&pHead, 8);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 6);
print(pHead);
bubble_sort(pHead);
print(pHead);
}
//查找中间节点,倒数第k个节点、删除倒数第k个节点
void test6()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 2);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
SlinkPushBack(&pHead, 5);
SlinkPushBack(&pHead, 6);
printf("%d\n", FindMiddleNode(pHead)->_data);
printf("%d\n", FindLastKNode(pHead, 6)->_data);
DeleteLastKNode(&pHead,2);
//print(pHead);
}
//合并两个链表
void test7()
{
pNode pHead1;
pNode pHead2;
SlinkInit(&pHead1);
SlinkInit(&pHead2);
SlinkPushBack(&pHead1, 1);
SlinkPushBack(&pHead1, 4);
SlinkPushBack(&pHead1, 6);
SlinkPushBack(&pHead1, 7);
SlinkPushBack(&pHead1, 9);
SlinkPushBack(&pHead2, 2);
SlinkPushBack(&pHead2, 3);
SlinkPushBack(&pHead2, 5);
SlinkPushBack(&pHead2, 8);
SlinkPushBack(&pHead2, 10);
pNode pCur = MergeList(pHead1,pHead2);
print(pCur);
}
//判断链表是否带环、相遇点、入口点、环的长度
void test8()
{
pNode pHead;
SlinkInit(&pHead);
SlinkPushBack(&pHead, 1);
SlinkPushBack(&pHead, 2);
SlinkPushBack(&pHead, 3);
SlinkPushBack(&pHead, 4);
SlinkPushBack(&pHead, 5);
SlinkPushBack(&pHead, 6);
SlinkPushBack(&pHead, 7);
SlinkPushBack(&pHead, 8);
SlinkPushBack(&pHead, 9);
pNode pCur = SListFind(&pHead, 9);
pCur->pNext = SListFind(&pHead, 6);
pCur = HasCircle(pHead);
printf("相遇点是%d\n", pCur->_data);
printf("环的长度%d\n", GetCircleLen(pHead));
printf("环的入口点%d\n", GetEnterNode(pHead, pCur)->_data);
}
//两个链表相交不带环球交点
void test9()
{
pNode pHead1;
pNode pHead2;
SlinkInit(&pHead1);
SlinkInit(&pHead2);
SlinkPushBack(&pHead1, 1);
SlinkPushBack(&pHead1, 2);
SlinkPushBack(&pHead1, 3);
SlinkPushBack(&pHead1, 4);
SlinkPushBack(&pHead1, 5);
SlinkPushBack(&pHead1, 6);
SlinkPushBack(&pHead1, 7);
SlinkPushBack(&pHead1, 8);
SlinkPushBack(&pHead1, 9);
SlinkPushBack(&pHead2, 10);
SlinkPushBack(&pHead2, 20);
SlinkPushBack(&pHead2, 30);
pNode pCur1 = SListFind(&pHead1, 5);
pNode pCur2 = SListFind(&pHead2, 30);
pCur2->pNext = pCur1;
pCur1 = GetCrossNode(pHead1, pHead2);
printf("%d\n", pCur1->_data);
}
//两个链表带环相交
void test10()
{
pNode pHead1;
pNode pHead2;
SlinkInit(&pHead1);
SlinkInit(&pHead2);
SlinkPushBack(&pHead1, 1);
SlinkPushBack(&pHead1, 2);
SlinkPushBack(&pHead1, 3);
SlinkPushBack(&pHead1, 4);
SlinkPushBack(&pHead1, 5);
SlinkPushBack(&pHead1, 6);
SlinkPushBack(&pHead1, 7);
SlinkPushBack(&pHead1, 8);
SlinkPushBack(&pHead1, 9);
SlinkPushBack(&pHead2, 10);
SlinkPushBack(&pHead2, 20);
SlinkPushBack(&pHead2, 30);
pNode pCur1 = SListFind(&pHead1,9);
pCur1->pNext = SListFind(&pHead1, 5);
pNode pCur2 = SListFind(&pHead2, 30);
pCur2->pNext = SListFind(&pHead1, 4);
int ret = IsCrossWithCircle(pHead1,pHead2);
printf("%d\n", ret);
//判断是环外相交还是环内相交
pCur1 = GetCrossNodeWith(pHead1, pHead2);
printf("%d\n", pCur1->_data);
}