#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int DataType;
typedef struct Node
{
DataType data;//數據域
struct Node* next;//保存下一個節點地址的指針域
}Node,*PNode;
void InitList(PNode* pHead)//初始化 傳二級指針
{
assert(pHead);
*pHead = NULL;
}
PNode BuyNode(DataType data)//申請新節點
{
PNode pTemp = (PNode)malloc(sizeof(Node));//申請空間
if(pTemp)//空間申請成功,若不成功直接返回NULL
{
pTemp->data = data;
pTemp->next = NULL;
}
return pTemp;
}
void PushBack(PNode* pHead, DataType data)//尾插
{
assert(pHead);
if(*pHead == NULL)//空鏈表
{
*pHead = BuyNode(data);
}
else//鏈表不爲空
{
PNode pcur = *pHead;
while(pcur->next)
{
pcur = pcur->next;
}
pcur->next = BuyNode(data);
}
}
void PopBack(PNode* pHead)//尾刪
{
assert(pHead);
if(*pHead == NULL)//鏈表爲空
{
return;
}
else if((*pHead)->next == NULL)//鏈表只有一個節點
{
free(*pHead);
*pHead = NULL;
}
else//鏈表有多個節點
{
PNode pcur = *pHead;
PNode pre = pcur;
while(pcur->next)
{
pre = pcur;
pcur = pcur->next;
}
free(pcur);
pre->next = NULL;
}
}
void PrintList(PNode pHead)//正序打印 不需二級指針,不改變外部實參
{
PNode pcur = pHead;
while(pcur)
{
printf("%d->",pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
///////////////////////////////////面試題1//////單鏈表逆置打印 遞歸//////////////////////////////////////////
void PrintTail2Head(PNode pHead)
{
if(pHead)
{
PrintTail2Head(pHead->next);
printf("%d->",pHead->data);
}
}
void PushFront(PNode* pHead, DataType data)//頭插
{
assert(pHead);
if(*pHead == NULL)//空鏈表與下面的非空情況可以合併到一起
{
*pHead = BuyNode(data);
}
else
{
PNode newnode = BuyNode(data);
if(newnode)//必須判斷新節點是否創建成功,成功纔可以插入
{
newnode->next = *pHead;//先將節點鏈接起來,否則可能丟失原鏈表
*pHead = newnode;//然後讓第一個節點的指針再指向新節點
}
}
}
void PopFront(PNode* pHead)//頭刪
{
assert(pHead);
if(pHead == NULL)//分兩種情況 鏈表爲空
{
return;
}
//非空
else
{
PNode pTemp = *pHead;//先保存第一個節點
*pHead = (*pHead)->next;//再讓第一個節點向後移動
free(pTemp);//釋放掉第一個節點
pTemp = NULL;
}
}
PNode Find(PNode pHead, DataType data)//查找data元素的位置
{
PNode pTemp = pHead;
while(pTemp)
{
if(pTemp->data == data)
{
return pTemp;
}
pTemp = pTemp->next;
}
return NULL;//不存在返回空
}
void Insert(PNode pos, DataType data)//在pos位置後插入元素
{
PNode newnode = NULL;//爲啥要先賦空???
if(pos == NULL)//插入位置是否合法
{
return;
}
newnode = BuyNode(data);//先申請新節點
newnode->next = pos->next;//讓新節點的next指向pos的next
pos->next = newnode;//然後讓pos的next指向新節點
}
void Erase(PNode* pHead, PNode pos)//要給出外部頭指針。因爲pos若爲頭結點 有可能改變頭結點的值
{
assert(pHead);//鏈表是否存在
if(pHead == NULL || pos == NULL)//鏈表爲空或位置不合法
{
return;
}
if(pos == *pHead)//刪除位置爲頭結點
{
*pHead = pos->next;//頭結點後移
free(pos);//刪除頭節點
}
else
{
PNode pcur = *pHead;
while(pcur->next != pos)
{
pcur = pcur->next;
}
pcur->next = pos->next;
free(pos);
}
}
/////////////////////////////////面試題2////////刪除非尾節點,不能遍歷鏈表 其實是刪除pos的下一個節點//////////////////
void DelNotTail(PNode pos)
{
PNode Delnode =NULL;
if(NULL == pos || pos->next ==NULL)
return;
Delnode = pos->next;
pos->data = Delnode->data;
pos->next = Delnode->next;
free(Delnode);
}
/////////////////////////////////面試題3/////////////在非頭結點前插入元素(頭結點也可以) 在pos後插 然後交換值///////////////
void InsertNotHead(PNode pos, DataType data)
{
PNode newnode = NULL;//?????????
if(pos == NULL)
return;
newnode = BuyNode(pos->data);
if(newnode)//必須判斷節點是否申請成功
{
newnode->next = pos->next;
pos->next = newnode;
pos->data = data;
}
}
void Remove(PNode pHead, DataType data)//刪除值爲data的元素,直接調用Erase函數(傳引用)與Find函數(不傳引用)
{
assert(pHead);
Erase(&pHead, Find(pHead, data));
}
void RemoveAll(PNode* pHead, DataType data)//刪除所有值爲data的元素!!!!!!!!!!!!!!!!!!!!!有問題
{
PNode pcur = NULL;
PNode pre = NULL;
assert(pHead);//鏈表是否存在
pre = *pHead;//定義兩個指針 一個指向第一個節點
pcur = pre->next;//指向第二個節點
while(pcur)//遍歷一遍單鏈表
{
if(pcur->data == data)//若pcur指向的節點值爲data
{
pre->next = pcur->next;
free(pcur);//釋放pcur
//pcur = pre;//讓pcur指向前一個
pcur = pre->next;
}
else
{
pcur = pcur->next;
}
}
if((*pHead)->data == data)//如果頭節點值爲data的情況
{
pcur = *pHead;
*pHead = (*pHead)->next;
free(pcur);
}
}
size_t Size(PNode pHead)//鏈表中元素個數
{
PNode pcur = NULL;
int count = 0;
assert(pHead);
pcur = pHead;
while(pcur)
{
count++;
pcur = pcur->next;
}
return count;
}
//PNode Front(PNode pHead)
//{
// assert(pHead);
// return pHead;
//}
PNode Back(PNode pHead)
{
PNode pcur = pHead;
if(NULL == pHead)
return NULL;
while(pcur->next)
{
pcur = pcur->next;
}
return pcur;
}
//int Empty(PNode pHead);
//////////////////////////////////////面試題//////////約瑟夫環/////////////////////////////////////////////
PNode JosephCircle(PNode pHead, size_t M)
{
PNode pCur = pHead;
PNode pTemp = NULL;
if(pHead == NULL)
return NULL;
while(pCur->next != pCur)
{
size_t count = M;
while(--count)
{
pCur = pCur->next;
}
pTemp = pCur->next;
pCur->data = pTemp->data;
pCur->next = pTemp->next;
free(pTemp);
}
return pCur;
}
//////////////////////////////////////////////測試////////////////////////////////////////////
void FunTest4()
{
PNode pHead, pos;
int count = 0;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
PushBack(&pHead, 5);
//Erase(&pHead, Find(pHead, 3));
//Remove(pHead, 2);
//RemoveAll(&pHead, 2);///////////有問題啊
/////////////////////////////////////////////約瑟夫環//////////////////////////////////////
pos = Back(pHead);//構環
pos->next = pHead;//構環
pHead = JosephCircle(pHead, 3);
pHead->next = NULL;
PrintList(pHead);
//count = Size(pHead);
//printf("%d\n",count);
}
void FunTest()
{
PNode pHead;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
PrintList(pHead);
PushFront(&pHead, 5);
PrintList(pHead);
PrintTail2Head(pHead);
PopBack(&pHead);
PrintList(pHead);
PopBack(&pHead);
PopBack(&pHead);
PrintList(pHead);
PopBack(&pHead);
PrintList(pHead);
PopBack(&pHead);
PrintList(pHead);
}
void FunTest1()
{
PNode pHead;
InitList(&pHead);
PushFront(&pHead, 1);
PushFront(&pHead, 2);
PushFront(&pHead, 3);
PushFront(&pHead, 4);
PrintList(pHead);
PopFront(&pHead);
PrintList(pHead);
PrintTail2Head(pHead);
}
void FunTest2()
{
PNode pHead, pos;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
pos = Find(pHead, 2);
Insert(pos,5);
PrintList(pHead);
Erase(&pHead, Find(pHead, 5));
PrintList(pHead);
Erase(&pHead, Find(pHead, 1));
PrintList(pHead);
DelNotTail(Find(pHead, 2));///只能刪除非尾節點
PrintList(pHead);
}
void FunTest3()
{
PNode pHead;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
PrintList(pHead);
InsertNotHead(Find(pHead, 2),5);
PrintList(pHead);
}
int main()
{
FunTest4();
system("pause");
return 0;
}
C語言實現單鏈表
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.