链表是一种常见的基础数据结构,是一种线性表,是一种物理存储单元上非连续、非顺序的存储结构。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括存储数据元素的数据域和存储下一个结点地址的指针域两个部分。 相比于线性表顺序结构,操作复杂。数据元素的逻辑顺序也是通过链表中的指针链接次序实现的。
给出头文件:
#ifndef __SLIST_H__
#define __SLIST_H__
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int DataType;
typedef struct Node
{
DataType data; //数据域
struct Node* next; //指针域
}Node; //节点的结构体
//打印
void SListPrint(Node *pFirst);
// 初始化
void SListInit(Node **ppFirst);
// 尾部插入
void SListPushBack(Node** ppFirst, DataType data);
// 头部插入
void SListPushFront(Node **ppFirst, DataType data);
// 尾部删除
void SListPopBack(Node **ppFirst);
// 头部删除
void SListPopFront(Node **ppFirst);
// 给定结点插入,插入到结点前
void SListInsert(Node **ppFirst, Node *pos, DataType data);
// 给定结点删除
void SListErase(Node **ppFirst, Node *pos);
// 按值删除,只删遇到的第一个
void SListRemove(Node **ppFirst, DataType data);
// 按值删除,删除所有的
void SListRemoveAll(Node **ppFirst, DataType data);
// 销毁
void SListDestroy(Node **ppFirst);
// 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL
int SListFind(Node *pFirst, DataType data);
#endif __SLIST_H__
接下来就实现如上功能
#include "SList.h"
void SListInit(Node **ppFirst)
{
assert(ppFirst);
*ppFirst = NULL;
}
void SListPrint(Node *pFirst)
{
Node* cur = pFirst;
while (cur != NULL)
{
printf("%d--->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
Node* NewNode(DataType data)
{
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
//尾插
void SListPushBack(Node** ppFirst, DataType data)
{
Node *node = NewNode(data);
assert(ppFirst != NULL);
if (*ppFirst == NULL)
{
*ppFirst = node;
return;
}
// 找链表中的最后一个结点 (链表中至少有一个结点)
Node *cur = *ppFirst;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = node;
}
//头插
void SListPushFront(Node **ppFirst, DataType data)
{
assert(ppFirst != NULL);
// 正常情况
Node *node = NewNode(data);
node->next = *ppFirst;
*ppFirst = node;
}
//尾删
void SListPopBack(Node **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL); // 链表不是空链表
if ((*ppFirst)->next == NULL) {
free(*ppFirst);
*ppFirst = NULL;
return;
}
// 链表中至少有两个结点,才能找倒数第二个
Node *cur = *ppFirst;
while (cur->next->next != NULL) {
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
//头删
void SListPopFront(Node **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL); // 链表不是空链表
Node *first = *ppFirst;
*ppFirst = (*ppFirst)->next;
free(first);
}
// 给定结点插入,插入到结点前
void SListInsert(Node **ppFirst, Node *pos, DataType data)
{
if (*ppFirst == pos) {
SListPushFront(ppFirst, data);
return;
}
Node *newNode = NewNode(data); // *** 不要忘了申请空间
Node *cur;
// 找到 pos 前的一个结点
for (cur = *ppFirst; cur->next != pos; cur = cur->next) {}
// 改变的是字段内的值,而不是指针的值
cur->next = newNode;
newNode->next = pos;
}
// 给定结点删除 (pos一定在链表中)
void SListErase(Node **ppFirst, Node *pos)
{
if (*ppFirst == pos) {
SListPopFront(ppFirst);
return;
}
Node *cur = *ppFirst;
while (cur->next != pos) {
cur = cur->next;
}
cur->next = pos->next;
free(pos); // 不要忘记释放结点
}
// 按值删除,只删遇到的第一个
void SListRemove(Node **ppFirst, DataType data)
{
Node* node = NULL;
Node* cur = NULL;
node = *ppFirst;
if (*ppFirst == NULL)
{
return;
}
else
{
while ((node->next)->data != data)
{
node = node->next;
}
cur = node->next;
node->next = cur->next;
free(cur);
}
}
// 按值删除,删除所有的
void SListRemoveAll(Node **ppFirst, DataType data)
{
Node* node = NULL;
Node* cur = NULL;
node = *ppFirst;
if (*ppFirst == NULL)
{
return;
}
else
{
while (node->next)
{
if ((node->next)->data == data)
{
cur = node->next;
node->next = cur->next;
free(cur);
cur = NULL;
}
else
{
node = node->next;
}
}
}
}
// 销毁
void SListDestroy(Node **ppFirst)
{
Node *cur, *next;
for (cur = ppFirst; cur != NULL; cur = next) {
next = cur->next;
free(cur);
cur = NULL;
}
}
// 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL
int SListFind(Node *pFirst, DataType data)
{
for (Node *cur = pFirst; cur != NULL; cur = cur->next) {
if (cur->data == data) {
return cur;
}
}
return NULL;
}
程序测试及结果如下:
#include "SList.h"
void test()
{
Node* list = NULL;//初始化链表
Node* pos = NULL;
printf("前插后:\n");
SListPushFront(&list, 1);
SListPushFront(&list, 2);
SListPushFront(&list, 3);
SListPushFront(&list, 4);
SListPushFront(&list, 5);
SListPrint(list);
printf("后插后:\n");
SListPushBack(&list, 1);
SListPushBack(&list, 2);
SListPushBack(&list, 3);
SListPushBack(&list, 4);
SListPushBack(&list, 5);
SListPrint(list);
printf("前删和后删:\n");
SListPopFront(&list);
SListPopFront(&list);
SListPopBack(&list);
SListPopBack(&list);
SListPrint(list);
//
printf("插入到指定位置:\n");
pos = SListFind(list, 2);
SListInsert(&list, pos, 100);
pos = SListFind(list, 3);
SListInsert(&list, pos, 0);
SListPrint(list);
printf("删除指定位置:\n");
pos = SListFind(list,1);
SListErase(&list,pos );
SListPrint(list);
printf("按值删除,只删遇到的第一个:\n");
SListRemove(&list, 3);
SListPrint(list);
printf("按值删除,只删所有:\n");
SListRemoveAll(&list, 2);
SListPrint(list);
//printf("销毁链表!");
//SListDestory(&list);
}
int main()
{
test();
}