目录
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
//链表节点结构体
typedef struct SLlistData
{
SLTDataType data;
struct SListData* next;
}SLTNode;
//单链表打印
void SLTPrint(SLTNode* phead);
//单链表后插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//单链表前插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//单链表尾删
void SLTPopBack(SLTNode** pphead);
//单链表头删
void SLTPopFront(SLTNode** pphead);
//动态申请一个节点
SLTNode* BuySLTNode(SLTDataType x);
//单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//pos之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//pos位置删除
void SLTErase(SLTNode** pphead, SLTNode* pos);
//pos后面插入
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//pos后面删除
void SLTEraseAfter(SLTNode* pos);
//单链表的销毁
void SListDestroy(SLTNode* phead);
1.链表的结构
typedef int SLTDataType;
//链表节点结构体
typedef struct SLlistData
{
SLTDataType data;
struct SListData* next;
}SLTNode;
2.函数实现
2.1单链表打印
void SLTPrint(SLTNode* phead)
{
//空链表可以打印,无需断言。链表有可能是空的(NULL),但是应该继续执行打印。
SLTNode* cur = phead;
//while (cur->next != NULL)
//顺序查询并打印列表
while (cur != NULL) // while (cur)
{
printf("%d->", cur->data);
cur = cur->next;//将current指向下一个节点地址(该地址在本结构体中next中存储着)
}
printf("NULL\n");//打印的是最后一个节点保存的地址
}
2.2动态申请一个节点
SLTNode* BuySLTNode(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//创建一个新的节点
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->data = x;//将该节点的数据位填充数据。
newnode->next = NULL;//将该节点的指针位填充指针。
return newnode;
}
2.3链表尾插
void SLTPushBack(SLTNode** pphead,SLTDataType x)
{
//assert(*pphead);//*pphead,照样可以打印。无需断言
assert(pphead);//如果为NULL,就报错
SLTNode* newnode = BuySLTNode(x);//获取生成的最新节点的地址,并将x写入该节点
if (*pphead == NULL)//如果是NULL,说明该链表是空链表
{
*pphead = newnode;
}
else //若不是,就找到该链表的最后一个节点
{
//找尾
SLTNode* tail = *pphead;//tail尾巴
while (tail->next != NULL)
{
tail = tail->next;//将tail指针移动到下一个节点的地址
}
tail->next = newnode;
}
}
2.4链表前插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
assert(pphead);//如果为NULL,就报错
SLTNode* newnode = BuySLTNode(x);//获取生成的最新节点的地址
newnode->next = *pphead;//将新节点的地址位 保存之前的起始地址
*pphead = newnode;//将链表的起始地址更新
}
2.4链表尾删
void SLTPopBack(SLTNode** pphead)
{
assert(pphead);//pphead不能为空,如果为空,就不可以进行尾删操作。
//暴力检查
assert(*pphead);
温柔的检查
//if(*pphead == NULL)
//{
// return;
//}
//1、只有一个节点
//2、多个节点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
// 找尾
SLTNode* prev = NULL; //tail的前一位
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
找尾
//SLTNode* tail = *pphead;
///*while (tail->next->next != NULL)*/
//while ( tail->next->next != NULL)
//{
// tail = tail->next;
//}
//free(tail->next);
//tail->next = NULL;
}
}
2.5链表头删
void SLTPopFront(SLTNode** pphead)
{
//暴力检查
assert(*pphead);
温柔的检查
//if (*pphead == NULL)
//{
// return;
//}
SLTNode* first = *pphead;
*pphead = first->next;
free(first);
first = NULL;
}
2.6查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
2.7 pos之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pos);//保证该位置是一个有效值,指针的有效性
assert(pphead);
if (pos == *pphead)//在链表首节点插入
{
SLTPushFront(pphead, x);
}
else
{
//找到pos的前一个位置
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
SLTNode* newnode = BuySLTNode(x);
prev->next = newnode;
newnode->next = pos;
}
}
2.8pos位置删除
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead);
assert(pos);
if (*pphead == pos)
{
SLTPopFront(pphead);
}
else
{
//找到pos的前一个位置
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
}
}
2.9pos后面插入
void SLTInserAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySLTNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
2.10pos位置后面删除
void SLTEraseAfter(SLTNode* pos)
{
assert(pos);
assert(pos->next);
SLTNode* del = pos->next;
pos->next = del->next;
free(del);
del = NULL;
}
2.11链表销毁
void SListDestroy(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur)
{
free(cur);
cur = cur->next;
}
}