链表:是一种物理存储上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序来实现的。
链表分类: 单向、双向
带头、不带头
循环、非循环
常用链表类型:
1.无头单向非循环链表
typedef struct Node{
int value; //保存链表每个节点的数值
struct Node* next; //结构体指针
} Node;
2.带头双向循环链表
typedef struct Node{
int value; //保存链表每个节点的数值
struct Node* next;
struct Node* prev; //
} Node;
本文只介绍单向链表
1.链表结构功能
SList.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#pragma once
//链表的节点
typedef struct Node
{
//结构体中的数值
int value;
//数组指针,存放每个数的地址
struct Node* next; //申请结构体指针数组,指向链表中数值的地址
} Node;
Node* first;
//单个链表元素申请
Node* BuyNode(int v);
//链表初始化
void SListInit(Node** pFirst);
//链表销毁
void SListDestory(Node* first);
//头插
void SListPushFront(Node** pFirst, int v);
//头删
void SListPopFront(Node** pFirst);
//尾插
void SListPushBack(Node** pFirst, int v);
//尾删
void SListPopBack(Node** pFirst);
//指定位置插
void SListInsert(Node* pos, int v);
//指定位置删
void SListErase(Node* pos);
//指定值查找
Node* SListFind(Node* first, int v);
//删除第一个遇到的指定值v
void SListRemove(Node** pFirst, int v);
//删除遇到的所有指定值v
void SListRemoveAll(Node** pFirst, int v);
//统计链表中的元素个数
int GetListLength(Node* first);
//打印链表中所有数字元素
void SListPrint(Node* first);
2.接口实现函数c实现
SList.c
#include "SList.h"
//单个链表元素申请
Node* BuyNode(int v)
{
//v = date_input();
Node* start = (Node*)malloc(sizeof(Node));
if (start == NULL)
{
perror("BuyNode::malloc");
return NULL;
}
start->value = v;
start->next = NULL;
return start;
}
//链表初始化
void SListInit(Node** pFirst)
{
*pFirst = NULL;
}
//链表销毁
void SListDestory(Node* first)
{
Node* next;
for (Node* cur = first; cur != NULL; cur = next)
{
next = cur->next;
free(cur);
}
}
//头插
void SListPushFront(Node** pFirst, int v)
{
Node* node = (Node*)malloc(sizeof(Node));
node->value = v;
node->next = *pFirst;
*pFirst = node;
}
//头删
void SListPopFront(Node** pFirst)
{
assert(*pFirst != NULL);
Node* next = (*pFirst)->next;
free(*pFirst);
*pFirst = next;
}
//尾插
void SListPushBack(Node** pFirst, int v)
{
//链表中没有元素的情况
if (*pFirst == NULL)
{
Node* node = (Node*)malloc(sizeof(Node));
node->value = v;
node->next = *pFirst;
*pFirst = node;
return;
}
//链表中有很多值的情况
Node* cur = *pFirst;
while (cur->next)
{
//让Node指针指向链表中最后一个元素的地址
cur = cur->next;
}
Node* node = (Node*)malloc(sizeof(Node));
node->value = v;
node->next = NULL;
cur->next = node;
}
//尾删
void SListPopBack(Node** pFirst)
{
assert(*pFirst != NULL);
//链表中只有一个元素
if ((*pFirst)->next == NULL)
{
free(*pFirst);
*pFirst = NULL;
return;
}
//多个元素
Node* cur = *pFirst;
while (cur->next->next)
{
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
//指定位置后插
// pos 肯定是链表中的结点
void SListInsertAfter(Node* pos, int v)
{
Node* node = (Node*)malloc(sizeof(Node));
node->value = v;
node->next = pos->next;
pos->next = node;
}
//指定位置的后面元素删
// pos 肯定是链表中的结点
void SListEraseAfter(Node* pos)
{
Node* next = pos->next;
pos->next = pos->next->next;
free(next);
}
//指定值查找
Node* SListFind(Node* first, int v)
{
for (Node* cur = first; cur != NULL; cur = cur->next)
{
if (cur->value == v)
{
return cur;
}
}
return NULL;
}
//删除第一个遇到的指定值v
void SListRemove(Node** pFirst, int v)
{
assert(*pFirst != NULL);
Node* cur = *pFirst;
if (cur->value == v)
{
Node* second = cur->next;
free(cur);
cur = second;
}
else
{
Node* prev = NULL;
while (cur && cur->value != v)
{
prev = cur; //循环结束时保存的是v前面结、点的地址
cur = cur->next; //循环结束时保存的是v结点的位置
}
prev->next = cur->next; //让v前面结点的next等于v的next
free(cur); //释放cur
cur = prev->next; //cur指向 它后面结点的地址
}
}
//删除遇到的所有指定值v
void SListRemoveAll(Node** pFirst, int v)
{
assert(*pFirst != NULL);
Node* cur = *pFirst;
Node* prev = cur->next;
//如果链表中只有一个节点且等于v
if (cur->value == v && cur->next == NULL)
{
free(cur);
cur = NULL;
return;
}
while (prev) //遍历让cur一直循环到最后一个节点
{
//cur没到最后一个节点,且prev节点值等于v时进入循环
while(prev != NULL && prev->value == v)
{
//删除指定节点cur后面的值
cur->next = prev->next;
free(prev);
prev = cur->next; //更新新的prev
}
if (prev == NULL)
{
return; //循环到最后一个节点退出
}
cur = cur->next; //进入下层循环
prev = prev->next;
}
}
//统计链表中的元素个数
int GetListLength(Node* first)
{
int count = 0;
if (first == NULL)
{
return 0;
}
Node* cur = first;
while (cur)
{
count++;
cur = cur->next;
}
return count;
}
//打印链表中所有数字元素
void SListPrint(Node* first)
{
if (first == NULL)
{
printf("链表为空!\n");
return;
}
Node* cur = first;
printf("链表中的值为:\n");
while (cur)
{
printf("%d\t", cur->value);
cur = cur->next;
}
printf("\n");
}
3.主测试程序
测试程序
main.c
#include "SList.h"
void test()
{
SListPushFront(&first, 1);
// 1 -> NULL
SListPushFront(&first, 2);
// 2 -> 1 -> NULL
SListPushFront(&first, 3);
// 3 -> 2 -> 1 -> NULL
SListPushFront(&first, 4);
// 4 -> 3 -> 2 -> 1 -> NULL
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
SListPushBack(&first, 10);
SListPushBack(&first, 20);
SListPushBack(&first, 30);
SListPushBack(&first, 40);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
// 4 3 2 1 10 20 30 40
SListPopBack(&first);
SListPopBack(&first);
SListPopBack(&first);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
// 4 3 2 1 10
SListPopFront(&first);
SListPopFront(&first);
SListPopFront(&first);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
// 1 10
SListPopBack(&first);
SListPopBack(&first);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
// first == NULL
}
void test1()
{
SListPushFront(&first, 1);
// 1 -> NULL
SListPushFront(&first, 2);
// 2 -> 1 -> NULL
SListPushFront(&first, 3);
// 3 -> 2 -> 1 -> NULL
SListPushFront(&first, 4);
// 4 -> 3 -> 2 -> 1 -> NULL
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
SListRemove(&first, 2);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
}
void test2()
{
SListPushBack(&first, 10);
SListPushBack(&first, 20);
SListPushBack(&first, 30);
SListPushBack(&first, 20);
SListPushBack(&first, 40);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
SListRemoveAll(&first, 20);
SListPrint(first);
printf("链表中元素总个数为:%d\n", GetListLength(first));
}
int main()
{
Node* first;
SListInit(&first);
//头插 尾插 头删 尾删
//test();
//删除第一个遇到的v
//test1();
//删除链表中所有v
test2();
system("pause");
return 0;
}