概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
无头单向非循环链表(单链表):结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
无头即第一个元素就是有效元素,单向非循环即只有next指针指向后一个链接的节点。
头文件 功能定义
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// 单向+不带头+非循环
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
SListNode* BuySListNode(SLTDateType x);//创建节点
void SListPrint(SListNode* plist);//打印链表
void SListPushBack(SListNode** pplist, SLTDateType x);//尾插,因为会修改链表结构,故要用二级指针来接收一级指针的参数
void SListPushFront(SListNode** pplist, SLTDateType x);//头插
void SListPopBack(SListNode** pplist);//尾删
void SListPopFront(SListNode** pplist);//头删
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);//返回一个节点
void SListInsertAfter(SListNode* pos, SLTDateType x);//pos后插入
void SListEraseAfter(SListNode* pos);//pos后删除
void SListDestory(Slist* plist);
函数功能实现
#include"SList.h"
SListNode* BuySListNode(SLTDateType x)
{
SListNode* node = (SListNode*)malloc(sizeof(SListNode));
node->data = x;
node->next = NULL;
return node;
}
void SListPrint(SListNode* plist)
{
SListNode* cur = plist;
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
void SListPushBack(SListNode** pplist, SLTDateType x)
{
SListNode* newnode = BuySListNode(x);
if (*pplist == NULL)//没有节点时直接覆盖
{
*pplist = newnode;
}
else//不为空时链接到尾部
{
SListNode* tail = *pplist;
while (tail->next)
{
tail = tail->next;
}//先找到尾节点
tail -> next = newnode;//在直接链接
}
}
void SListPushFront(SListNode** pplist, SLTDateType x)
{
SListNode* newnode = BuySListNode(x);
if (*pplist == NULL)//为空时直接覆盖
{
*pplist = newnode;
}
else//为空
{
newnode->next = *pplist;//头插
*pplist = newnode;//更新头部
}
}
void SListPopBack(SListNode** pplist)//尾删
{
SListNode* prev = NULL;
SListNode* tail = *pplist;
if (*pplist == NULL || tail->next == NULL)//为空或者只有一个节点
{
free(tail);
*pplist == NULL;
}
else//有两个以上节点
{
while (tail->next)
{
prev = tail;//保留前一个结点
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
void SListPopFront(SListNode** pplist)//头删
{
SListNode* prev = *pplist;
if (*pplist == NULL || prev->next == NULL)//为空或只有一个节点
{
free(prev);
*pplist = NULL;
}
else
{
SListNode* next = prev->next;//先保留下一个
free(prev);
*pplist = next;//更新头部
}
}
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
if (plist == NULL)
{
return NULL;
}
SListNode* cur = plist;
while (cur->next)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
assert(pos);
SListNode* cur = pos;
SListNode* newnode = BuySListNode(x);
newnode->next = cur->next->next;
cur->next = newnode;
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{
assert(pos);
SListNode* next= pos->next;//保留pos下一个节点
if (next)
{
pos->next = next->next;
free(next);
}
}
功能测试
#include <stdio.h>
#include "SList.h"
void TestSList1()
{
SListNode* plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListPrint(plist);
SListPopBack(&plist);
SListPrint(plist);
SListPopBack(&plist);
SListPrint(plist);
SListPopBack(&plist);
SListPrint(plist);
SListPopBack(&plist);
SListPrint(plist);
}
void TestSList2()
{
SListNode* plist = NULL;
SListPushFront(&plist, 1);
SListPushFront(&plist, 2);
SListPushFront(&plist, 3);
SListPushFront(&plist, 4);
SListPrint(plist);
}
void TestSList3()
{
SListNode* plist = NULL;
SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPushBack(&plist, 3);
SListPushBack(&plist, 4);
SListNode* ret=SListFind(plist,2);//查找返回的是节点,或者为空
if (ret != NULL)
ret->data = 100;//找到后修改这个节点的值
SListPrint(plist);
SListNode* pos = SListFind(plist, 100);
SListInsertAfter(pos, 200);//两个功能配合使用,先找到节点,再传参,再在此节点后插入
SListPrint(plist);
SListNode* pos1 = SListFind(plist, 100);
SListEraseAfter(pos1);
SListPrint(plist);
}
int main()
{
TestSList3();
return 0;
}