实现单链表的以下操作:
list.h:
#ifndef __LIST_H__
#define __LIST_H__
#include
#include
#include
typedef int DataType;
typedef struct Node
{
DataType _data;
struct Node *_pNext;
}Node,*pNode;
// 初始化单链表
void InitList(pNode* pHead);
// 在单链表的尾部插入一个节点
void PushBack(pNode* pHead, DataType data);
// 删除单链表的最后一个节点
void PopBack(pNode* pHead);
// 在单链表的头部插入值为data的结点
void PushFront(pNode* pHead, DataType data);
// 删除单链表的第一个结点
void PopFront(pNode* pHead);
// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(pNode pHead, DataType data);
// 在单链表pos位置后插入值为data的结点
void Insert(pNode pos, DataType data);
// 在单链表中删除位置为pos的结点
void Erase(pNode* pHead, pNode pos);
// 移除单链表中第一个值为data的结点
void Remove(pNode* pHead, DataType data);
// 移除单链表中所有值为data的结点
void RemoveAll(pNode* pHead, DataType data);
// 获取单链表总结点的总个数
size_t Size(pNode pHead);
// 判断结点是否为空
DataType Empty(pNode pHead);
// 返回单链表的最后一个结点的位置
pNode Back(pNode pHead);
// 返回单链表的第一个结点的位置
pNode Front(pNode pHead);
// 构建一个新节点
Node* BuyNode(DataType data);
// 正向打印单链表
void PrintList(pNode pHead);
//单链表实现约瑟夫环
void JosiphCircle(pNode *pHead,size_t M);
///面试题//
//12.24实现无头单链表的以下操作:
// 逆序打印单链表
void PrintFromTail2Head(pNode pHead);
// 删除单链表的非尾结点(不能遍历单链表)
void DeleteNotTailNode(pNode pos);
// 使用递归实现从未到头打印单链表
void PrintFromTail2Head(pNode pHead);
// 删除单链表的非尾结点
void DeleteNotTailNode(pNode pos);
// 在单链表非头结点前插入结点data
void InsertNotHeadNode(pNode pos, DataType data);
// 查找单链表的中间结点,要求只便利一次链表
pNode FindMidNode(pNode pHead);
// 查找单链表的倒数第K个结点,要求只遍历一次链表
pNode FindLastKNode(pNode pHead, size_t k);
// 使用冒泡排序对单链表进行排序
void BubbleSort(pNode pHead);
// 判断两个单链表是否相交(链表不带环)
int IsListCross(pNode L1, pNode L2);
// 若不带环的单链表相交,求交点
pNode GetCrossNode(pNode PL1, pNode PL2);
//12.25实现链表的以下操作:
// 实现单链表的逆置:使用三个指针
pNode ReverseList(pNode pHead);
// 实现单链表的逆置:使用头插法
void ReverseList_P(pNode* pHead);
// 合并两个已序单链表,合并后依然有序
pNode MergeList(pNode pHead1, pNode pHead2);
// 判断链表是否带环,若带环给出相遇点
pNode HasCircle(pNode pHead);
// 求环的长度
size_t GetCircleLen(pNode pMeetNode);
// 求环的入口点
pNode GetEnterNode(pNode pHead, pNode pMeetNode);
// 判断链表是否相交,注意:链表可能带环
int IsCrossWithCircle(pNode pHead1, pNode pHead2);
#endif //__LIST_H__
List.c:
#include "List.h"
void InitList(pNode *pHead)
{
assert(pHead);
*pHead = NULL;
}
// 在单链表的尾部插入一个节点
void PushBack(pNode* pHead, DataType data)
{
assert(pHead);
if(*pHead == NULL)
{
*pHead = BuyNode(data);
}
else
{
Node *pTailNode = *pHead;
while(pTailNode->_pNext)
{
pTailNode = pTailNode->_pNext;
}
pTailNode->_pNext = BuyNode(data);
}
}
//构建一个新节点
static Node* BuyNode(DataType data)
{
Node *pNewNode = (Node *)malloc(sizeof(Node));
if(pNewNode != NULL)
{
pNewNode->_data = data;
pNewNode->_pNext = NULL;
}
return pNewNode;
}
//删除单链表的最后一个节点
void PopBack(pNode* pHead)
{
assert(pHead);
if(pHead == NULL)
{
return;
}
else if((*pHead)->_pNext == NULL)
{
free(*pHead);
*pHead = NULL;
}
else
{
Node *pPreNode = *pHead;
Node *pTailNode = *pHead;
while(pTailNode->_pNext)
{
pPreNode = pTailNode;
pTailNode = pTailNode->_pNext;
}
free(pTailNode);
pPreNode->_pNext = NULL;
}
}
// 正向打印单链表
void PrintList(pNode pHead)
{
Node *pCurNode = pHead;
while(pCurNode)
{
printf("%d->",pCurNode->_data);
pCurNode = pCurNode->_pNext;
}
printf("NULL\n");
}
// 在单链表的头部插入值为data的结点
void PushFront(pNode* pHead, DataType data)
{
assert(pHead);
if(*pHead == NULL)
{
*pHead = BuyNode(data);
}
else
{
pNode pNewNode = BuyNode(data);
pNewNode->_pNext = *pHead;
*pHead = pNewNode;
}
}
// 删除单链表的第一个结点
void PopFront(pNode* pHead)
{
assert(pHead);
if(*pHead == NULL)
{
return;
}
else if((*pHead)->_pNext == NULL)
{
free(*pHead);
*pHead = NULL;
}
else
{
Node *pDelNode = *pHead;
*pHead = (*pHead)->_pNext;
free(pDelNode);
}
}
// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(pNode pHead, DataType data)
{
Node *pCurNode = pHead;
while(pCurNode)
{
if(pCurNode->_data == data)
{
return pCurNode;
}
pCurNode = pCurNode->_pNext;
}
return NULL;
}
//在单链表pos位置后插入值为data的结点
void Insert(pNode pos, DataType data)
{
Node *pNewNode = NULL;
if(pos == NULL)
{
return;
}
pNewNode = BuyNode(data);
if(pNewNode == NULL)
{
return;
}
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
}
// 在单链表非头结点前插入结点data
void InsertNotHeadNode(pNode pos, DataType data)
{
pNode pNewNode = BuyNode(pos->_data);
if(pNewNode == NULL)
{
return;
}
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
pos->_data = data;
}
//在单链表中删除位置为pos的结点
void Erase(pNode* pHead, pNode pos)
{
assert(pHead);
if(NULL == *pHead || NULL == pos)
{
return;
}
else if(*pHead == pos)
{
PopFront(pHead);
}
else
{
Node *pPreNode = *pHead;
while(pPreNode->_pNext != pos)
{
pPreNode = pPreNode->_pNext;
}
pPreNode->_pNext = pos->_pNext;
free(pos);
}
}
//移除单链表中第一个值为data的结点(非尾结点)
void Remove(pNode* pHead, DataType data)
{
pNode pPreNode = Find(*pHead,data);
if(pPreNode == NULL)
{
return;
}
else
{
pNode pDelNode = pPreNode->_pNext;
pPreNode->_data = pPreNode->_pNext->_data;
pPreNode->_pNext = pPreNode->_pNext->_pNext;
free(pDelNode);
}
}
//移除单链表中第一个值为data的结点
void Remove(pNode* pHead, DataType data)
{
pNode pPreNode = Find(*pHead,data);
assert(pHead);
if(pPreNode == NULL)
{
return;
}
else
{
Erase(pHead,pPreNode);
}
}
//移除单链表中所有值为data的结点(递归)
void RemoveAll(pNode* pHead, DataType data)
{
pNode pDelNode = NULL;
Remove(pHead,data);
pDelNode = Find(*pHead,data);
if(pDelNode == NULL)
{
return;
}
else
{
RemoveAll(pHead,data);
}
}
//移除单链表中所有值为data的结点
void RemoveAll(pNode* pHead, DataType data)
{
pNode pPre = *pHead;
pNode pCur = *pHead;
pCur = pPre->_pNext;
if(*pHead == NULL)
{
return;
}
while(pCur)
{
if(pCur->_data == data)
{
pPre->_pNext = pCur->_pNext;
free(pCur);
pCur = pPre->_pNext;
}
else
{
pPre = pCur;
pCur = pCur->_pNext;
}
}
if((*pHead)->_data == data)
{
pNode pTemp = *pHead;
*pHead = pTemp->_pNext;
free(pTemp);
}
}
//移除单链表中所有值为data的结点(非尾结点)
void RemoveAll(pNode* pHead, DataType data)
{
pNode pPreNode = *pHead;
while(pPreNode)
{
pPreNode = Find(pPreNode,data);
if(pPreNode == NULL)
{
return;
}
else
{
pNode pDelNode = pPreNode->_pNext;
pPreNode->_data = pPreNode->_pNext->_data;
pPreNode->_pNext = pPreNode->_pNext->_pNext;
free(pDelNode);
}
}
}
//删除单链表的非尾结点(不能遍历单链表)
void DeleteNotTailNode(pNode pos)
{
assert(pos);
if(pos->_pNext == NULL)
{
return;
}
else
{
pNode pDelNode = pos->_pNext;
pos->_data = pDelNode->_data;
pos->_pNext = pDelNode->_pNext;
free(pDelNode);
}
}
//逆序打印单链表
void PrintFromTail2Head(pNode pHead)
{
if(pHead == NULL)
{
return;
}
else
{
PrintFromTail2Head(pHead->_pNext);
printf("%d->",pHead->_data);
}
}
//获取单链表总结点的总个数
size_t Size(pNode pHead)
{
int count = 0;
pNode pPreNode = pHead;
while(pPreNode)
{
count++;
pPreNode = pPreNode->_pNext;
}
return count;
}
// 判断结点是否为空
DataType Empty(pNode pHead)
{
if(pHead == NULL)
{
return 0;
}
else
return 1;
}
//返回单链表的最后一个结点的位置
pNode Back(pNode pHead)
{
pNode pTailNode = pHead;
while(pTailNode->_pNext)
{
pTailNode = pTailNode->_pNext;
}
return pTailNode;
}
//返回单链表的第一个结点的位置
pNode Front(pNode pHead)
{
return pHead;
}
//单链表实现约瑟夫环
void JosiphCircle(pNode *pHead,size_t M)
{
int m = M;
pNode pCurNode = NULL;
assert(pHead);
if(*pHead == NULL)
{
return;
}
pCurNode = *pHead;
while(pCurNode != pCurNode->_pNext)
{
pNode pDelNode = NULL;
m = M;
while(--m)
{
pCurNode = pCurNode->_pNext;
}
pDelNode = pCurNode->_pNext;
pCurNode->_data = pDelNode->_data;
pCurNode->_pNext = pDelNode->_pNext;
free(pDelNode);
}
*pHead = pCurNode;
(*pHead)->_pNext = NULL;
}
// 查找单链表的中间结点,要求只遍历一次链表
pNode FindMidNode(pNode pHead)
{
pNode pFast = NULL;
pNode pSlow = NULL;
if(pHead == NULL)
{
return NULL;
}
pFast = pHead;
pSlow = pHead;
while(pFast && pFast->_pNext)
{
pSlow = pSlow->_pNext;
pFast = pFast->_pNext->_pNext;
}
return pSlow;
}
// 查找单链表的倒数第K个结点,要求只遍历一次链表
pNode FindLastKNode(pNode pHead, size_t k)
{
pNode pFast = NULL;
pNode pSlow = NULL;
if(pHead == NULL || k == 0)
{
return NULL;
}
pFast = pHead;
pSlow = pHead;
while(k--)
{
pFast = pFast->_pNext;
}
while(pFast)
{
pFast = pFast->_pNext;
pSlow = pSlow->_pNext;
}
return pSlow;
}
// 使用冒泡排序对单链表进行排序
void BubbleSort(pNode pHead)
{
pNode pTailNode = NULL;
pNode pPre = NULL;
pNode pCur = NULL;
int flag = 0;
if(pHead == NULL || pHead->_pNext == NULL)
{
return;
}
pPre = pHead;
pCur = pHead;
while(pHead != pTailNode)
{
pPre = pHead;
pCur = pPre->_pNext;
while(pCur != pTailNode)
{
if(pPre->_data > pCur->_data)
{
DataType temp = 0;
flag = 1;
temp = pPre->_data;
pPre->_data = pCur->_data;
pCur->_data = temp;
}
pPre = pCur;
pCur = pCur->_pNext;
}
if(flag == 0)
{
return;
}
pTailNode = pPre;
}
}
// 判断两个单链表是否相交(链表不带环)
int IsListCross(pNode L1, pNode L2)
{
pNode pCurNode1 = NULL;
pNode pCurNode2 = NULL;
if(L1 == NULL || L2 == NULL)
{
return 0;
}
pCurNode1 = L1;
pCurNode2 = L2;
while(pCurNode1->_pNext)
{
pCurNode1 = pCurNode1->_pNext;
}
while(pCurNode2->_pNext)
{
pCurNode2 = pCurNode2->_pNext;
}
if(pCurNode1 == pCurNode2)//两不带环的单链表相交尾节点必相同
{
return 1;
}
else
return 0;
}
// 若不带环的单链表相交,求交点
pNode GetCrossNode(pNode pL1, pNode pL2)
{
size_t s1 = 0;
size_t s2 = 0;
int gap = 0;
if(IsListCross(pL1,pL2) == 0)
{
return NULL;
}
s1 = Size(pL1);
s2 = Size(pL2);
gap = s1 - s2;
if(gap < 0)
{
gap = -gap;
while(gap--)
{
pL2 = pL2->_pNext;
}
}
else
{
while(gap--)
{
pL1 = pL1->_pNext;
}
}
while(pL1 != pL2)
{
pL1 = pL1->_pNext;
pL2 = pL2->_pNext;
}
return pL1;
}
// 实现单链表的逆置:使用三个指针
pNode ReverseList(pNode pHead)
{
pNode pPreNode = NULL;
pNode pCurNode = NULL;
pNode pNextNode = NULL;
if(pHead == NULL || pHead->_pNext == NULL)
{
return NULL;
}
pPreNode = pHead;
pCurNode = pPreNode->_pNext;
pNextNode = pCurNode->_pNext;
while(pNextNode)
{
pCurNode->_pNext = pPreNode;
pPreNode = pCurNode;
pCurNode = pNextNode;
pNextNode = pNextNode->_pNext;
}
pCurNode->_pNext = pPreNode;
pHead->_pNext = NULL;
pHead = pCurNode;
return pHead;
}
// 实现单链表的逆置:使用头插法
void ReverseList_P(pNode* pHead)
{
pNode pNewHead = NULL;
pNode pPreNode = NULL;
pNode pCurNode = NULL;
if(*pHead == NULL || (*pHead)->_pNext == NULL)
{
return;
}
pPreNode = *pHead;
pCurNode = (*pHead)->_pNext;
while(pCurNode)
{
pPreNode->_pNext = pNewHead;
pNewHead = pPreNode;
pPreNode = pCurNode;
pCurNode = pCurNode->_pNext;
}
pPreNode->_pNext = pNewHead;
pNewHead = pPreNode;
*pHead = pNewHead;
}
// 合并两个已序单链表,合并后依然有序
pNode MergeList(pNode pHead1, pNode pHead2)
{
pNode pL1 = NULL;
pNode pL2 = NULL;
pNode pNewHead = NULL;
pNode pTailNode = NULL;
if(pHead1 == NULL)
{
return pHead2;
}
if(pHead2 == NULL)
{
return pHead1;
}
pL1 = pHead1;
pL2 = pHead2;
if(pL1->_data <= pL2->_data)
{
pNewHead = pL1;
pTailNode = pNewHead;
pL1 = pL1->_pNext;
}
else
{
pNewHead = pL2;
pTailNode = pNewHead;
pL2 = pL2->_pNext;
}
while(pL1 && pL2)
{
if(pL1->_data <= pL2->_data)
{
pTailNode->_pNext = pL1;
pL1 = pL1->_pNext;
}
else
{
pTailNode->_pNext = pL2;
pL2 = pL2->_pNext;
}
pTailNode = pTailNode->_pNext;
}
if(pL1 != NULL)
{
pTailNode->_pNext = pL1;
}
if(pL2 != NULL)
{
pTailNode->_pNext = pL2;
}
return pNewHead;
}
// 判断链表是否带环,若带环给出相遇点
pNode HasCircle(pNode pHead)
{
pNode pFast = NULL;
pNode pSlow = NULL;
if(pHead == NULL)
{
return NULL;
}
pFast = pHead;
pSlow = pHead;
//环内点都是相遇点
while(pFast && pFast->_pNext)
{
pSlow = pSlow->_pNext;
pFast = pFast->_pNext->_pNext;
if(pSlow == pFast)
{
return pSlow;
}
}
return NULL;
}
// 求环的长度
size_t GetCircleLen(pNode pMeetNode)
{
pNode pCurNode = pMeetNode;
size_t count = 1;
while(pCurNode->_pNext != pMeetNode)
{
pCurNode = pCurNode->_pNext;
count++;
}
return count;
}
// 求环的入口点
pNode GetEnterNode(pNode pHead, pNode pMeetNode)
{
pNode pH = NULL;
pNode pM = NULL;
if(pHead == NULL || pMeetNode == NULL)
{
return NULL;
}
pH = pHead;
pM = pMeetNode;
while(pH != pM)
{
pH = pH->_pNext;
pM = pM->_pNext;
}
return pH;
}
// 判断链表是否相交,注意:链表可能带环
//(两个链表都带环或都不带环)
int IsCrossWithCircle(pNode pHead1, pNode pHead2)
{
pNode pMeetNode1 = HasCircle(pHead1);
pNode pMeetNode2 = HasCircle(pHead2);
if(pMeetNode1 == NULL && pMeetNode2 == NULL)
{
pNode pCurNode1 = pHead1;
pNode pCurNode2 = pHead2;
if(pHead1 == NULL || pHead2 == NULL)
{
return 0;
}
while(pCurNode1->_pNext)
{
pCurNode1 = pCurNode1->_pNext;
}
while(pCurNode2->_pNext)
{
pCurNode2 = pCurNode2->_pNext;
}
if(pCurNode1 == pCurNode2)
{
return 1; //不带环相交
}
}
else if(pMeetNode1 != NULL && pMeetNode2 != NULL)
{
pNode pCurNode = pMeetNode1;
while(pCurNode->_pNext != pMeetNode1)
{
if(pCurNode == pMeetNode2)
{
return 2; //带环环外相交
}
pCurNode = pCurNode->_pNext;
}
if(pCurNode == pMeetNode2)
{
return 2; //带环环内相交(环的入口点相交)
}
}
return 0;
}