链表和顺序表一样,都是线性表,逻辑结构上是线性的,但不同的是,链表在物理结构上不是线性的
链表是由一个一个节点构成的,一个节点分为两部分:存储的数据和指针(结构体指针)
其中的指针存储的是该节点指向的下一个节点的地址
一个节点的结构体可以这样表示:
cpp
typedef int SLDataType;
typedef struct SListNode
{
int date;
struct SListNode* next;
}SLTNode;
一.链表的打印
cpp
void SLTPrint(SLNode * phead)
{
SLTNode* pcur = phead;
while(pcur != NULL)
{
printf("%d->",pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
二.链表的尾插
cpp
void SLTPushBack(SLTNode** pphead,SLTDataType x)
{
if(pphead == NULL)//如果为空,则根本不存在链表,自然不能插入
return;
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
//链表存在,但是内容为空,新节点作为phead
if(*pphead == NULL)
*pphead = newnode;
return;
//链表不为空
SLTNode* ptail = *pphead;
while(ptail->next != NULL)
ptail = ptail->next;
ptail->next = newnode;
}
注意:需要改变的是指针的值,因此在传参时需要传入指针的地址,,因此函数需要一个二级指针作为形参
三.链表的头插
cpp
//申请一个新节点
SLTNode* SLTBuyNode(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
void SLTPushFront(SLTNode** pphead,SLTDataType x)
{
if(pphead == NULL)//如果为空,则根本不存在链表,自然不能插入
return;
SLTNode* newnode = SLTBuyNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
四.链表的尾删
cpp
void SLTPopBack(SLTNode** pphead)
{
if(pphead == NULL)
return;
if(*pphead == NULL)
return;
//链表只有一个节点
if((*pphead)->next == NULL)
free(*pphead);
*pphead = NULL;
return;
//链表有多个节点
SLTNode* ptail = *pphead;//尾节点
SLTNode* prev = NULL;//尾节点的前一个节点
while(ptail->next != NULL)
{
prev = ptail;
ptail = ptail->next;
}
prev->next = NULL;
free(ptail);
ptail = NULL;
}