#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct Node
{
struct Node* _pNext;
DataType _data;
}Node, *PNode;
// 删除链表的非尾结点,要求不能遍历链表
void DeleteNotTailNode(PNode pos);
// 在链表pos位置前插入值为data的结点
void InsertPosFront(PNode pos, DataType data);
// 约瑟夫环
void JosephCircle(PNode* pHead, const int M);
// 使用冒泡方式对单链表进行排序
void BubbleSort(PNode pHead);
// 单链表的逆序---三个指针
void ReverseSList(PNode* pHead);
// 单链表的逆序---使用头插法
PNode ReverseSListOP(PNode pHead);
// 合并两个有序链表,合并起来依然要有序
PNode MergeSList(PNode pHead1, PNode pHead2, PNode pHead3);
// 查找链表的中间结点,要求只能遍历一次链表
PNode FindMiddleNode(PNode pHead);
// 查找链表的倒数第K个结点
PNode FindLastKNode(PNode pHead, int K);
// 判断单链表是否相交?链表不带环
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);
// 删除链表的非尾结点,要求不能遍历链表
void DeleteNotTailNode(PNode pos)
{
PNode pCur = NULL;
if (pos)
{
pCur= pos->_pNext;
pos->_data = pCur->_data;
pos->_pNext = pCur->_pNext;
free(pCur);
}
}
// 在链表pos位置前插入值为data的结点
void InsertPosFront(PNode pos, DataType data)
{
PNode pCur = NULL;
if (!pos)
{
pCur = BuySListNode(pos->_data);//创建一个新节点
pos->_data = data;
pCur->_pNext = pos->_pNext;
pos->_pNext = pCur;
}
}
// 约瑟夫环
void JosephCircle(PNode* pHead, const int M)
{
PNode pCur = NULL;
PNode pDel = NULL;
assert(pHead);
if (NULL == pHead)
return;
pCur = pHead;
//构环
while (pCur->_pNext)
{
pCur = pCur->_pNext;
}
pCur->_pNext =pHead ;
pCur = pHead;
while (pCur != pCur->_pNext)
{
//记数
int count = M;
while (--count)
{
pCur = pCur->_pNext;
}
//删节点
pDel = pCur->_pNext;
pCur->_data = pDel->_data;
pCur->_pNext = pDel->_pNext;
free(pDel);
}
//解环
pCur->_pNext = NULL;
return pCur;
}
// 使用冒泡方式对单链表进行排序
void BubbleSort(PNode pHead)
{
PNode cur = NULL;
PNode tail = NULL;
assert(pHead);
cur = pHead->_pNext;
while (cur != tail)
{
while (cur->_pNext != tail)
{
if (cur->_data > cur->_pNext->_data)
{
DataType tmp = cur->_data;
cur->_data = cur->_pNext->_data;
cur->_pNext->_data = tmp;
}
cur = cur->_pNext;
}
tail = cur;
cur = pHead->_pNext;
}
return;
}
// 单链表的逆序---三个指针
void ReverseSList(PNode* pHead)
{
PNode p1, p2, p3;
assert(pHead);
if (NULL == pHead)
return pHead;
p1 = pHead;
p2 = p1->_pNext;
while (p2)
{
p3 = p2->_pNext;
p2->_pNext = p1;
p1 = p2;
p2 = p3;
}
(*pHead)->_pNext = NULL;
*pHead = p1;
return pHead;
}
// 单链表的逆序---使用头插法
PNode ReverseSListOP(PNode pHead)
{
PNode pCur = NULL;
PNode p = NULL;
assert(pHead);
if (NULL == pHead)
return pHead;
pCur = pHead->_pNext; // 建立一个空表
pHead->_pNext = NULL;
while (!pCur)
{
p = pCur->_pNext;
pCur->_pNext = pHead->_pNext;
pHead->_pNext = pCur;
pCur = p;
}
}
// 合并两个有序链表,合并起来依然要有序
PNode MergeSList(PNode pHead1, PNode pHead2,PNode pHead3)
{
PNode pa=NULL; //pa pb分别指向 pHead1 和 pHead2 中待比较插入的节点
PNode pb=NULL;
PNode pc=NULL; //pc指向 pHead3 最后一个节点
pa = pHead1->_pNext;
pb = pHead2->_pNext;
pHead3 = pc = pHead1;
while (pa && pb)
{
if (pa->_data <= pb->_data)//将pa所指的节点链接到pc所指向的节点后面
{
pc->_pNext = pa;
pc = pa;
pa = pa->_pNext;
}
else //将pb所指向的节点链接到pc所指向的节点后面
{
pc->_pNext = pb;
pc = pb;
pb = pb->_pNext;
}
}
pc->_pNext = pa ? pa : pb;
free(pHead2);
}
// 查找链表的中间结点,要求只能遍历一次链表
PNode FindMiddleNode(PNode pHead)
{
assert(pHead);
PNode pFast = pHead;
PNode pSlow = pHead;
while (NULL != pHead || NULL != pHead->_pNext)
{
pFast = pFast->_pNext->_pNext;
pSlow = pSlow->_pNext;
}
return pSlow;
}
// 查找链表的倒数第K个结点
PNode FindLastKNode(PNode pHead, int K)
{
PNode pFast = NULL;
PNode pSlow = NULL;
assert(pHead);
if (NULL == pHead)
return 0;
pFast = pHead;
pSlow = pHead;
int count = 0;
while (NULL != pFast) //遍历一次,让指针走到最后一个结点
{
if (count < K) //如果count<k,让快指针先走到k节点处
{
count++;
pFast = pFast->_pNext;
}
else //让快慢指针一起走
{
pSlow = pSlow->_pNext;
pFast = pFast->_pNext;
}
}
if (count < K)
return 0; //找不到返回0
else
printf("%d", pSlow->_data); //找到返回1,并打印 k 结点值
return 1;
}
// 判断单链表是否相交?相交求交点,链表不带环
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2)
{
assert(pHead1);
assert(pHead2);
PNode pTail1 = pHead1;
PNode pTail2 = pHead2;
if (NULL == pHead1 || NULL == pHead2);
return 0;
while (pTail1 && pTail1->_pNext)
{
pTail1 = pTail1->_pNext++;
}
while (pTail2 && pTail2->_pNext)
{
pTail2 = pTail2->_pNext++;
}
if ((pTail1 == pTail2) && (NULL != pTail1))
return 1;
else
return NULL;
}
// 求不带环单链表相交交点
PNode GetCrossNode(PNode pHead1, PNode pHead2)
{
assert(pHead1);
assert(pHead2);
PNode pTail1 = pHead1;
PNode pTail2 = pHead2;
DataType len1 = 0;
DataType len2 = 0;
DataType Sub = 0;
if (NULL == pHead1 || NULL == pHead2);
return 0;
while (pTail1 && pTail1->_pNext)
{
pTail1 = pTail1->_pNext;
len1++;
}
while (pTail2 && pTail2->_pNext)
{
pTail2 = pTail2->_pNext;
len2++;
}
if (pTail1 != pTail2)
{
return NULL;
}
Sub = len1 - len2;
if ((0 == Sub) && (pTail1 == pTail2)) //pTail1 和pTail2长度相等
{
return 1;
}
else if (Sub > 0) //pTail1比pTail2长 ,让pTail2先走他们的Sub步,然后一起走
{
while (Sub != 0)
{
pTail2 = pTail2->_pNext;
Sub--;
}
while (pTail1 != pTail2)
{
pTail1 = pTail1->_pNext;
pTail2 = pTail2->_pNext;
}
return 1;
}
else //pTail2比pTail1长 ,让pTail1先走他们的Sub步,然后一起走
{
while (Sub !=0)
{
pTail1 = pTail1->_pNext;
Sub--;
}
while (pTail1 != pTail2)
{
pTail1 = pTail1->_pNext;
pTail2 = pTail2->_pNext;
}
return 1;
}
}
// 判断链表是否带环
PNode IsCircle(PNode pHead)
{
assert(pHead);
PNode pFast = pHead;
PNode pSlow = pHead;
while (pFast && pFast->_pNext)
{
pFast = pFast->_pNext->_pNext;
pSlow = pSlow->_pNext;
}
if (pFast == pSlow)
{
printf("链表带环\n");
return pSlow;
}
else
return NULL;
}
// 求环的长度
int GetCircleLen(PNode pHead)
{
DataType i = 0;
PNode pCur = pHead;
while (pCur->_pNext != pHead)
{
++i;
pCur = pCur->_pNext;
}
return i;
}
// 求环的入口点--注意推断过程
//链表总长度=起始点到入口点长度+环的长度
//有结论得出:起始点到入口点长度 == 相遇点的长度到入口点的长度
PNode GetEnterNode(PNode pHead, PNode pMeetNode)
{
PNode pEnterNode = NULL;
PNode pCur1 = pHead;
PNode pCur2 = pMeetNode;
while (pCur1 != pCur2)
{
pCur1 = pCur1->_pNext;
pCur2 = pCur2->_pNext;
}
pEnterNode = pCur1;
return pEnterNode;
}
//判断链表是否带环,链表可能带环
int IsListCrossWithCircle(PNode pHead1, PNode pHead2)
{
assert(pHead1);
assert(pHead2);
//判断两个链表是否带环
PNode pCur1 = IsCircle(pHead1);
PNode pCur2 = IsCircle(pHead2);
PNode pEnter1 = NULL;
PNode pEnter2 = NULL;
PNode pCrossNode = NULL;
if (NULL == pCur1 && NULL == pCur2)//两个都不带环
{
pCrossNode = GetEnterNode(pCur1, pCur2); //相交求交点
return 0;
}
else if ((NULL == pCur1 && NULL != pCur2) || (NULL != pCur1 && NULL == pCur2))//如果一个带环一个不带环
{
return -1;
}
else //两个都带环
{
PNode pMeet = pCur1->_pNext;
while (pMeet !=pCur1)
{
if (pMeet == pCur2)//两个环相交
{
pEnter1 = GetEnterNode(pHead1, pCur1);
pEnter2 = GetEnterNode(pHead2, pCur2);
if (pEnter1 == pEnter2)
{
printf("环外相交\n");
pCrossNode = GetEnterNode(pCur1, pCur2); //相交求交点
return 1;
}
else
{
printf("环内相交\n");
return 2;
}
}
pMeet = pMeet->_pNext;
}
return -1; //不相交
}
}
数据结构之链表面试题(约瑟夫环,判断链表带环求交点问题)
最新推荐文章于 2020-11-25 13:36:34 发布