實作鏈表的頭插
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"slist.h"
//鏈表的概念及結構
//鏈表是一種物理存盤結構上非連續,非順序的存盤結構,資料元素的邏輯結構是通過鏈表中的指標來鏈接
void testslist()
{
slistnode*plist = NULL;//一開始定義一個指標,但啥都沒有,所以先賦值空指標,作為頭節點,存入第一個節點的地址
slistpushback(&plist, 1);//尾插//也要傳地址才可以,實參傳給形參,形參是實參的臨時拷貝
slistpushback(&plist, 2);
slistpushback(&plist, 3);
slistpushback(&plist, 4);
slistpushfront(&plist, 0);//頭插
slistpopback(&plist);
slistpopfront(&plist);//頭刪
slistprint(plist);
}
int main()
{
//需要定義一個指標指向頭部
testslist();
return 0;
}
slist.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"slist.h"
void slistprint(slistnode*phead)
{
slistnode*cur = phead;
while (cur != NULL)//遍歷是cur不等于空就往下走,走到尾部還不等于空,走到下一個節點,是空的
{
printf("%d->", cur->date);
cur = cur->next;//cur指向下一個指標
}
printf("NULL\n");
}
//開辟節點做的事情很多次,所以直接用一個函式去做開辟節點的事情就可以了
slistnode*buynode(slistdate x)
{
slistnode*newnode = (slistnode*)malloc(sizeof(slistnode));// 要尾插就要動態開辟一個節點出來
newnode->date = x;//將newnode初始化
newnode->next = NULL;//把next賦值為空
return newnode;
}
void slistpushback(slistnode**pphead, slistdate x)
{
slistnode*newnode = buynode(x);
//那么我們這個時候要找尾
//找到尾節點的指標
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
slistnode*tail = *pphead;//我們要讓tail走到尾部去,而非走到空
while (tail->next != NULL)
{
tail = tail->next;
}//找到了尾節點,鏈接新節點
tail->next=newnode;
}
}
void slistpushfront(slistnode**pphead, slistdate x)
{
//頭插
//也要malloc出來一個節點
slistnode*newnode = buynode(x);
newnode->next = *pphead;//指向頭節點,隨后要讓phead存第一個節點的地址
*pphead = newnode;//phead存入newnode地址,phead作為頭節點,就把newnode當作了頭節點
}
//尾刪要分3種情況分析
//1.沒有節點
//2.一個節點
//3.多個節點
void slistpopback(slistnode**pphead)//尾刪
{
//1.想洗掉就找到那個節點,free掉就可以了,因為都是malloc出來的
//但是,如果將tail找到了那個尾節點,直接free掉,那么前一個節點的指標就會變成野指標,它的指標仍有存在值,但是沒有指向的目標,
//因此,我們要找到它的前一個節點,再定義一個prev,作為尾節點找到最后一個節點,他的前一個節點
//1.沒有節點,即*pphead沒有指向,就直接回傳不用洗掉
if (*pphead == NULL)
{
return;
}
//只有一個節點
else if ((*pphead)->next == NULL)//由于*和->的優先級相同,所以為了不報錯,就應該把*pphead用括號包含
{
//直接free掉8
free(*pphead);
*pphead = NULL;//再將*pphead置成空指標,防止它變成野指標
}
//有多個節點
else
{
//先定義tail用來找尾,prev找尾前一個節點
slistnode*tail = *pphead;
slistnode*prev = NULL;//prev置成空指標
//找尾節點
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
//此時prev就是尾節點
free(tail);
prev->next = NULL;
}
}
void slistpopfront(slistnode**pphead)//頭刪
{
//先保存它下一個指標,next
slistnode*next = (*pphead)->next;//next保存第二個節點的地址,之后將其作為第一個節點
//洗掉頭節點
free(*pphead);
*pphead = next;
}
slist.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int slistdate;//對int重命名,只會方便把int改成double或其他資料型別
struct slistnode
{
slistdate date;//
struct slistnode*next;//指標地址,指向下一個節點
};
typedef struct slistnode slistnode;//方便寫
//可能會改變鏈表的頭指標就傳二級指標
void slistpushback(slistnode**pphead, slistdate x);//尾插
void slistpushfront(slistnode**pphead, slistdate x);//頭插
//不會改變鏈表的頭指標,就傳一級指標
void slistprint(slistnode*phead);
void slistpopback(slistnode**pphead);//尾刪
void slistpopfront(slistnode**pphead);//頭刪
1.頭插實作
void slistpushfront(slistnode**pphead, slistdate x)
{
//頭插
//也要malloc出來一個節點
slistnode*newnode = buynode(x);
newnode->next = *pphead;//指向頭節點,隨后要讓phead存第一個節點的地址
*pphead = newnode;//phead存入newnode地址,phead作為頭節點,就把newnode當作了頭節點
}

2.頭刪
void slistpopfront(slistnode**pphead)//頭刪
{
//先保存它下一個指標,next
slistnode*next = (*pphead)->next;//next保存第二個節點的地址,之后將其作為第一個節點
//洗掉頭節點
free(*pphead);
*pphead = next;
}
4.尾刪
//尾刪要分3種情況分析
//1.沒有節點
//2.一個節點
//3.多個節點
void slistpopback(slistnode**pphead)//尾刪
{
//1.想洗掉就找到那個節點,free掉就可以了,因為都是malloc出來的
//但是,如果將tail找到了那個尾節點,直接free掉,那么前一個節點的指標就會變成野指標,它的指標仍有存在值,但是沒有指向的目標,
//因此,我們要找到它的前一個節點,再定義一個prev,作為尾節點找到最后一個節點,他的前一個節點
//1.沒有節點,即*pphead沒有指向,就直接回傳不用洗掉
if (*pphead == NULL)
{
return;
}
//只有一個節點
else if ((*pphead)->next == NULL)//由于*和->的優先級相同,所以為了不報錯,就應該把*pphead用括號包含
{
//直接free掉8
free(*pphead);
*pphead = NULL;//再將*pphead置成空指標,防止它變成野指標
}
//有多個節點
else
{
//先定義tail用來找尾,prev找尾前一個節點
slistnode*tail = *pphead;
slistnode*prev = NULL;//prev置成空指標
//找尾節點
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
//此時prev就是尾節點
free(tail);
prev->next = NULL;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/347130.html
標籤:其他
