slist.h//頭文件
#ifndef _SLIST_H_
#define _SLTST_H_
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SListNode;
void SListInit(SListNode** pphead);
void SListDestory(SListNode** pphead);
SListNode* BuySListNode(SLTDataType x);
void SListPushFront(SListNode** pphead, SLTDataType x);
void SListPopFront(SListNode** pphead);
SListNode* SListFind(SListNode* pphead, SLTDataType x); // 在pos的後面進行插入
void SListInsertAfter(SListNode* pos, SLTDataType x); // 在pos的前面進行插入
void SListEraseAfter(SListNode* pos);
void SListRemove(SListNode** pphead, SLTDataType x);
void SListRemoveAll(SListNode** pphead, SLTDataType x);
void SListPrint(SListNode* pphead);
void SListReverse(SListNode **pphead);
void SListReverse2(SListNode **pphead);
SListNode* getIntersectionNode(SListNode* headA, SListNode*headB);
SListNode *detectCycle(SListNode *head);
#endif
slist.c//源文件
#include"slist.h"
void SListInit(SListNode** pphead)//初始化
{
*pphead = NULL;
}
void SListDestory(SListNode** pphead)
{
if (*pphead == NULL)
{
return;
}
else
{
while ((*pphead)->next)
{
SListEraseAfter(*pphead);
}
free(*pphead);
*pphead = NULL;
}
}
SListNode* BuySListNode(SLTDataType x)
{
SListNode* res = (SListNode *)malloc(sizeof(SListNode));
res->data = x;
res->next = NULL;
return res;
}
void SListPushFront(SListNode** pphead, SLTDataType x)
{
SListNode* tmp = BuySListNode(x);
tmp->next = *pphead;
*pphead = tmp;
}
void SListPopFront(SListNode** pphead)
{
if (*pphead == NULL)
{
return;
}
/*(*pphead)->date = (*pphead)->next;*/
SListNode* tmp = (*pphead)->next;
free(*pphead);
*pphead = tmp;
}
SListNode* SListFind(SListNode* pphead, SLTDataType x)//找x數據
{
SListNode* tmp;
for (tmp = pphead; tmp; tmp = tmp->next)
{
if (tmp->data == x)
{
return tmp;
}
return NULL;
}
}
void SListInsertAfter(SListNode* pos, SLTDataType x)//把x插到pos後面
{
SListNode* tmp = BuySListNode(x);
tmp->next = pos->next;
pos->next = tmp;
}
void SListEraseAfter(SListNode* pos)//刪除pos後面的數據
{
SListNode* tmp = pos->next;
if (tmp == NULL)
{
return;
}
pos->next = tmp->next;
free(tmp);
}
void SListRemove(SListNode** pphead, SLTDataType x)//移除x
{
SListNode* tmp;
if (*pphead == NULL)
{
return;
}
if ((*pphead)->data==x)
{
SListPopFront(*pphead);
}
else
{
for (tmp = *pphead; tmp->next; tmp = tmp->next)
{
SListEraseAfter(pphead);
return;
}
}
}
void SListRemoveAll(SListNode** pphead, SLTDataType x)
{
SListNode* tmp;
if (*pphead && (*pphead)->data == x)
{
SListPopFront(*pphead);
}
for (; tmp = *pphead; tmp&&tmp->next)
{
if (tmp->next == x)
{
SListEraseAfter(tmp);
}
else
{
tmp = tmp->next;
}
}
}
void SListPrint(SListNode* pphead)
{
SListNode* cur;
printf("pphead->");
for (cur = pphead; cur; cur = cur->next)
{
printf("%d->", cur->data);
}
printf("NULL\n");
}
void SListReverse(SListNode **pphead)//反轉鏈表
{
SListNode *head = *pphead; //此指針在每次循環中始終指向當前鏈表的頭
SListNode *tmp = head->next; //此指針在每次循環中始終指向要被後刪頭插的節點
SListNode *oldh = *pphead; //此指針在每次循環中始終指向原本的頭結點,不會改變指向
while (tmp) //如果tmp爲空,則代表逆序結束,舊頭的next已經是空的了,成爲新鏈表的末尾
{
oldh->next = tmp->next; //將tmp架空,實際是後刪操作的一部分
tmp->next = head; //讓tmp變成新的頭,實際是頭插操作的一部分
head = tmp; //換頭
tmp = oldh->next; //讓tmp變成下次循環中待刪除的節點
}
*pphead = head;
}
void SListReverse2(SListNode **pphead)//反轉鏈表
{
SListNode *pre = *pphead; //被執行操作的前一個節點
SListNode *cur = pre->next; //被執行操作的節點
SListNode *next = cur; //被執行操作的後一個節點,暫時指在cur,在循環開始的時候跳轉到其後一個節點
pre->next = NULL; //此時的頭,將會是轉換後的尾,這裏是在設置鏈表尾節點
while (next)
{
next = next->next; //先讓next變成下一個節點,之所以不放在最後,是因爲會有next爲空的限制
cur->next = pre; //讓原本指着後面的指到前面來(先後轉)
pre = cur; //爲了下次循環而傳遞數據,這裏是設置下次循環的上一個節點(本次執行操作的節點將會成下次循環的上一個節點)
cur = next; //同上(本次的下一個節點將會成爲下次的被執行節點)
}
*pphead = pre; //循環跳出後cur和next都已經指向空了,pre纔是新的頭
}
//輸入兩個鏈表,找出它們的第一個公共結點
SListNode* getIntersectionNode(SListNode* headA, SListNode*headB)
{
int lenA = 0;
int lenB = 0;
int gap, i;
SListNode* cur = 0;
SListNode * longerlist = headA;
SListNode * shorterlist = headB;
for (cur = 0; cur; cur = headA->next)
{
lenA++;
}
for (cur = 0; cur; cur = headB->next)
{
lenB++;
}
gap = abs(lenA - lenB);
if (lenA > lenB)
{
longerlist = headA;
shorterlist = headB;
}
else
{
longerlist = headB;
shorterlist = headA;
}
for (i = 0; i < gap; i++)
{
longerlist=longerlist->next;
}
for (; longerlist&&shorterlist; longerlist = longerlist->next, shorterlist = shorterlist->next)
{
if (longerlist == shorterlist)
{
return longerlist;
}
}
return NULL;
}
// 給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 NULL
SListNode *detectCycle(SListNode *head)
{
SListNode * fast = head;
SListNode * slow = head;
while (fast && slow && fast->next)
{
fast = fast->next->next;//遍歷速度爲2
slow = slow->next;//遍歷速度爲1
if (fast == slow)//判斷兩不同遍歷速度的交點
{
break;
}
}
for (; fast && fast->next; fast = fast->next, head = head->next)//交點到入環的第一個節點距離等於頭節點到入環的第一個節點
{
if (fast == head)
{
return fast;
}
}
return NULL;
}
main.c//測試
#include"slist.h"
#if 0 //1,選擇程序段
int main()//測試
{
SListNode *phead1;
//SListNode *phead2;
SListNode *tmp;
SListNode *tmp2;
SListInit(&phead1);
//SListInit(&phead2);
SListPushFront(&phead1, 8);
tmp = phead1;
SListPushFront(&phead1, 7);
SListPushFront(&phead1, 6);
SListPushFront(&phead1, 5);
SListPushFront(&phead1, 4);
SListPushFront(&phead1, 3);
tmp2 = phead1;
SListPushFront(&phead1, 2);
SListPushFront(&phead1, 1);
tmp->next = tmp2;
//phead2->next = phead1->next->next;
SListNode * ret = detectCycle(phead1);
if (ret)
{
printf("%d\n", ret->data);
}
else
{
printf("NULL\n");
}
//SListDestory(&phead1);
//SListDestory(&phead2);
return 0;
}
#else
int main()//測試
{
SListNode *phead;
SListInit(&phead);
SListPushFront(&phead, 1);
SListPushFront(&phead, 2);
SListPushFront(&phead, 3);
SListPushFront(&phead, 4);
SListPushFront(&phead, 5);
SListPushFront(&phead, 6);
SListPushFront(&phead, 7);
SListPushFront(&phead, 8);
SListPushFront(&phead, 9);
//SListPopFront(&phead);
//SListPopFront(&phead);
/*
SListInsertAfter(SListFind(phead, 6), 9);
SListEraseAfter(SListFind(phead, 4));
SListRemove(&phead, 7);
SListPrint(phead);
*/
//SListRemoveAll(&phead, 8);
SListReverse2(&phead);
SListPrint(phead);
SListDestory(&phead);
//SListPrint(phead);
return 0;
}
#endif
//int main()//約瑟夫環問題,鏈表解決
//{
// SListNode *phead;
// SListNode *plast;
// SListNode *cur;
// int m = 11, n = 3;
// int i;
// SListInit(&phead);
// SListPushFront(&phead, m);
// plast = phead;
// for (i = m - 1; i >= 1; i--)
// {
// SListPushFront(&phead, i);
// }
// plast->next = phead;
// cur = plast;
// for (; m > 1; m--)
// {
// for (i = 1; i < n; i++)
// {
// cur = cur->next;
// printf("%d號報數字%d\n", cur->data, i);
// }
// printf("%d號被去掉\n", cur->next->data);
// SListEraseAfter(cur);
// }
// printf("%d號最終獲勝\n", cur->data);
// free(cur);
// return 0;
//}