链表
链表是一种在物理存储上无规则的存储结构,由指针将每个数据元素来串联起来。
链表可以从单向双向、带头不带头、循环非循环来进行分类,最常用的是无头单向非循环链表和带头双向链表。
无头单向链表:结构简单实现容易,但是一般不会用来存储数据,更多的是用来实现一些其他数据结构的子结构,如哈希桶、邻接表等。
带头双向循环链表:结构复杂,一般用来存储数据,其数据结构带来许多操作的优势。
单向链表结构定义:
typedef int SLTypeData;
typedef struct SListNode
{
SLTypeData data;
struct SListNode* next;
}SListNode,SLn;
void SListPrint(SListNode* phead);//打印数据
void SListPushBack(SListNode** pphead, SLTypeData x);//尾插
void SListPushFront(SListNode** pphead, SLTypeData x);//头插
void SListPopBack(SListNode** pphead);//尾删
void SListPopFront(SListNode** pphead);//头删
SListNode* SListFind(SListNode* phead, SLTypeData x);//寻找数据
void SListInsert(SListNode** pphead, SListNode* pos, SLTypeData x);//在pos之前插入
void SListErase(SListNode** pphead, SListNode* pos);//删除数据
SListNode* BuySListNode(SLTypeData x);//建立数据
void SListEraseAfter(SListNode* pos);//删除pos后数据
尾删和尾插实现
void SListPushBack(SListNode** pphead, SLTypeData x) {
assert(pphead);//检查数据是否为空
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL) {
printf("malloc fail\n");
exit(-1);
}
else {
newnode->data = x;
newnode->next = NULL;
}//如果malloc成功就插入数据
if (*pphead == NULL) {
*pphead = newnode;
}//头节点为空直接在其后插入
else{
SListNode* tail = *pphead;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = newnode;
}//若头节点不为空则找到最后一个节点在其后插入
}
void SListPopBack(SListNode** pphead) {
assert(pphead);//检查是否为空
if (*pphead == NULL) {//头节点为空
return;
}
else if ((*pphead)->next == NULL) {//只有一个结点
free(*pphead);
*pphead = NULL;
}
else {//多个结点
SListNode* prev = NULL;
SListNode* tail = *pphead;
while (tail->next != NULL) {
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
!!!一定要传入二级指针,形参其实是实参的复制,而传入指针相当于传入指针的复制,如果没有传回指针的话在函数结束后函数栈帧会自动删除形参,此时找不到已经操作好的数据,所以要传入二级指针,对指针进行直接操作。
头插头删
void SListPushFront(SListNode** pphead, SLTypeData x) {
assert(pphead);//检查是否为空
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL) {
printf("malloc fail\n");
exit(-1);
}
else {
newnode->data = x;
newnode->next = NULL;
}//建立节点
newnode->next = *pphead;
*pphead = newnode;
}
void SListPopFront(SListNode** pphead) {
assert(pphead);//检查是否为空
if (*pphead == NULL) {
return;
}
else {
SListNode* next = (*pphead)->next;
free(*pphead);
*pphead = next;
}
}
插入节点
void SListInsert(SListNode** pphead, SListNode* pos, SLTypeData x) {
assert(pphead);
assert(pos);//检查是否为空
if (pos == *pphead) {
SListPushFront(pphead, x);
}//pos为头节点
else {
SListNode* prev = *pphead;
while (prev->next != pos) {
prev = prev->next;
}
SListNode* newnode = BuySListNode(x);
prev->next = newnode;
newnode->next = prev->next;
}
}//在pos前插入
void SListInsertAfter(SListNode* pos, SLTypeData x) {
assert(pos);
SListNode* next = pos->next;
SListNode* newnode = BuySListNode(x);
pos->next = newnode;
newnode = next;
}//在pos后插入
删除节点
void SListErase(SListNode** pphead, SListNode* pos) {
assert(pphead);
assert(pos);
if (*pphead == pos) {
SListPopFront(pphead);
}
else {
SListNode* prev = *pphead;
while (prev->next != pos) {
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}//删除pos处数据
void SListEraseAfter(SListNode* pos) {
assert(pos);
SListNode* next = pos->next;
if (next) {
pos->next = next->next;
free(next);
next = NULL;
}
}//删除pos后数据
按值寻找节点
SListNode* SListFind(SListNode* phead, SLTypeData x) {
SListNode* cur = phead;
while (cur != NULL) {
if (cur->data == x) {
return cur;
}
cur = cur->next;
}
return NULL;
}
打印链表
void SListPrint(SListNode* phead) {
SListNode* cur = phead;
while (cur != NULL) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
销毁链表
void SListDestroy(SListNode** pphead) {
assert(pphead);
SListNode* cur = *pphead;
while (cur) {
SListNode* next = cur->next;
free(cur);
cur = next;
}
pphead = NULL;
}
主函数
#include"SList.h"
int main() {
SListNode* head = NULL;
SListNode* s1 = malloc(sizeof(SListNode));
SListNode* s2 = malloc(sizeof(SListNode));
SListNode* s3 = malloc(sizeof(SListNode));
head = s1;
s1->data = 1;
s2->data = 2;
s3->data = 3;
s1->next = s2;
s2->next = s3;
s3->next = NULL;
SListPushBack(&s3, 4);
SListPrint(head);
SListPopBack(&head);
printf("\n");
SListPrint(head);
SListNode* pos = SListFind(s1, 3);
if (pos)
{
SListInsert(&s1, pos, 30);
}
SListPrint(head);
pos = SListFind(head, 3);
if (pos)
{
SListErase(&head, pos);
}
SListPrint(head);
return 0;
}