单链表的结构
单链表的结构其实就是一个连续的结构体,可以把这个结构体看成一个一室一厅的房子,卧室放要存储的数据,餐厅放指向下一个房子的指针(其实就是下一个房子的地址)。链表通过访问指针去找到下一个链表,构成一个线性结构。
链表可分为带(不带)哨兵位头结点,循环与非循环链表,以下演示非循环不带哨兵位的链表
接口函数
//尾插
void SListPushBack(SLTNode** pphead, SListDataType x);
//打印链表
void SListPrint(SLTNode* phead);
//头插
void SListPushFront(SLTNode** pphead, SListDataType x);
//尾删
void SListPopBack(SLTNode** pphead);
//头删
void SListPopFront(SLTNode** pphead);
//寻找链表当中的元素
SLTNode* SListFind(SLTNode* phead,SListDataType x);
//pos位置之前插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SListDataType x);
//删除指定元素
void SListRemoveElement(SLTNode** pphead, SListDataType x);
//pos位置之后插入
void SListInsertAfter(SLTNode** pphead, SLTNode* pos, SListDataType x);
接口函数的实现
(其中SLTNode*plist只是一个指针用来存储头结点的地址,可以认为*pphead就是头结点的地址)
typedef int SListDataType;
//定义一个结构体
typedef struct SListNode
{
SListDataType data;
//用来存储下一个节点的地址
struct SListNode* next;
}SLTNode;
//创建链表
SLTNode* BuySListNode(SListDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
perror("newnode");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//为什么传二级指针:因为我在main函数当中定义的是SLTNode*plist=NULL;定义了一个结点的地址,而我要改变 结点所存储的内容,在main函数当中传参就要&plist才能改变plist里存储的内容,plist是一级指真,&plist就要用二级指针来接受
void SListPushBack(SLTNode** pphead, SListDataType x)
{
SLTNode* newnode = BuySListNode(x);
//不能写成*pphead->next,因为这时访问越界;
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void SListPrint(SLTNode* phead)
{
//assert(phead->next != NULL);
SLTNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL");
printf("\n");
}
void SListPushFront(SLTNode** pphead, SListDataType x)
{
SLTNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
void SListPopBack(SLTNode** pphead)
{
//if (*pphead == NULL)
//{
// return -1;
//}
assert(*pphead != NULL);
//链表当中就一个数据
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
SLTNode* prev = NULL;
SLTNode* tail = *pphead;
//找尾结点,以及尾结点的前一个
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
prev->next = NULL;
free(tail);
tail = NULL;
}
}
void SListPopFront(SLTNode** pphead)
{
assert(*pphead!=NULL);
//找到头结点的下一个节点
SLTNode* next = (*pphead)->next;
free(*pphead);
*pphead = next;
}
SLTNode* SListFind(SLTNode* phead,SListDataType x)
{
SLTNode* find = phead;
while (find != NULL)
{
if (find->data == x)
{
return find;
}
find = find->next;
}
return NULL;
}
//pos位置之前去插入
void SListInsert(SLTNode** pphead,SLTNode*pos, SListDataType x)
{
assert(pos != NULL);
if (pos == *pphead)
{
SLTNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
else
{
SLTNode* prev = *pphead;
//找pos位置前一个节点
while ((prev)->next != pos)
{
prev = prev->next;
}
SLTNode* newnode = BuySListNode(x);
prev->next = newnode;
newnode->next = pos;
}
}
void SListRemoveElement(SLTNode** pphead, SListDataType x)
{
SLTNode* cur = *pphead;
SLTNode* prev = NULL;
while (cur)
{
//找到了分两种情况
if (cur->data == x)
{
// 第一种是在头结点
if (cur == *pphead)
{
*pphead = cur->next;
free(cur);
cur = *pphead;
}
// 第二种是在中间节点
else
{
prev->next = cur->next;
free(cur);
cur = prev->next;
}
}
else
{
prev = cur;
cur = cur->next;
}
}
}
void SListInsertAfter(SLTNode** pphead, SLTNode* pos,SListDataType x)
{
SLTNode*newnode=BuySListNode(x);
newnode->next = pos->next;
pos->next = newnode;
}