目录
单链表
1、链表要执行的功能
为了保持代码的规范以下函数声明和变量的声明写在头文件中,
// 1、无头+单向+非循环链表增删查改实现
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);
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);
2、创建一个结构体
结构体组成了链表的每一个节点
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;//指向结构体的地址
}SListNode;
3、创建节点和打印链表
// 动态申请一个结点
SListNode* BuySListNode(SLTDateType x) {
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));//动态申请空间
if (newnode == NULL) {
perror("malloc");
return;
}
newnode->data = x;//传的x的值
newnode->next = NULL;
return newnode;
}
// 单链表打印
void SListPrint(SListNode* plist) {
SListNode* cur = plist;
while (cur) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
4、单链表尾插
对上述链表进行尾插如下:
// 单链表尾插
//传结构体指针只能改变结构体的成员变量但不能改变结构体地址,
//当第一个节点为空时要将新节点的地址赋给空节点的地址所以要用双指针
void SListPushBack(SListNode** pplist, SLTDateType x) {
assert(pplist);//即使第一个节点为空但是空指针也有地址所以,pplist不可能为NULL
SListNode* newnode = BuySListNode(x);
//有两种情况
// 1、首节点为NULL
if (*pplist == NULL)
*pplist = newnode;
//2、首节点不为NULL
else {
SListNode* tail = *pplist;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = newnode;
}
}
5、 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x) {
arrest(pplist);
SListNode* newhead = BuySListNode(x);
//有两种情况
// 1、首节点为NULL
if (*pplist == NULL)
*pplist = newhead;
//2、首节点不为NULL
newhead->next = *pplist;//将新的节点的下一个指向原来的首节点
*pplist = newhead;
}
6、单链表的尾删
// 单链表的尾删
void SListPopBack(SListNode** pplist) {
assert(pplist);
assert(*pplist);//第一个节点不为空
//一个节点
if ((*pplist)->next == NULL) {
free(*pplist);
*pplist = NULL;
}
//一个以上节点
else {
SListNode* tail = *pplist;
while (tail->next->next == NULL) {//根据图可知要删除NULL的前一个得找到NULL的前一个的前一个才能将尾节点置为空
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
7、单链表头删
// 单链表头删
void SListPopFront(SListNode** pplist) {
assert(pplist);
assert(*pplist);//第一个节点不为空
SListNode* newphead = (*pplist)->next;//当只有一个节点时(*pplist)->next==NULL
//这里不可以直接把*pplist给newphead,因为给了之后就没有办法将头节点给删除了
free(*pplist);
*pplist = newphead;
}
8、单链表查找
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x) {
while (plist) {
if (plist->data == x)
return plist;
plist = plist->next;
}
return NULL;
}
9、 单链表在pos位置之后插入x
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x) {
SListNode* newnode = BuySListNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
10、单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos) {
assert(pos);
// 检查pos是否是尾节点,和只有一个指针
assert(pos->next);
SListNode* posNext = pos->next;
pos->next = posNext->next;
free(posNext);
posNext = NULL;
}