代码大纲
单链表实现分析
以下代码实现了单链表的基本操作,包括创建、插入、删除、查找和修改等功能。每个函数的功能和实现方式如下:
链表节点创建
c
SLNode* SLBuNode(Etype x)
{
SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
if (newnode == NULL)
{
perror("Malloc");
exit(1);
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
该函数用于动态分配一个新节点,并初始化其数据和指针字段。如果内存分配失败,程序会报错并退出。
头指针初始化
c
void SLHandInit(SLNode* L)
{
assert(L);
L->data = 0;
L->next = NULL;
}
初始化头指针,设置链表长度为0,并清空next指针。
链表销毁
c
void SLDestroy(SLNode* L)
{
assert(L);
SLNode* p = L->next;
while (p != NULL)
{
SLNode* temp = p;
p = p->next;
free(temp);
}
L->next = NULL;
L->data = 0;
}
释放链表所有节点内存,重置头指针状态。
链表打印
c
void SLPrint(SLNode* L)
{
assert(L);
SLNode* p = L->next;
while (p != NULL)
{
printf("%d->", p->data);
p = p->next;
}
printf("NULL\n");
}
遍历链表并打印每个节点的数据值。
数据插入操作
c
void SLPushFront(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
q->next = p;
L->next = q;
L->data++;
}
在链表头部插入新节点。
c
void SLPushBack(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
if (L->next == NULL)
{
L->next = q;
}
else
{
while (p->next != NULL)
{
p = p->next;
}
p->next = q;
}
L->data++;
}
在链表尾部插入新节点。
c
void SLPushN(SLNode* L, Etype x, int n)
{
assert(L);
if (L->next == NULL)
{
printf("L NULL!\n");
return;
}
if (n > L->data)
{
printf("n超过了SList长度\n");
return;
}
else if (n == 0)
{
SLPushFront(L, x);
return;
}
else if (n < 0)
{
printf("n < 0\n");
return;
}
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
SLNode* pre = p->next;
for (int i = 1; i < n; i++)
{
p = pre;
pre = pre->next;
}
p->next = q;
q->next = pre;
L->data++;
}
在指定位置后插入新节点,包括边界条件检查。
数据删除操作
c
void SLPopFront(SLNode* L)
{
assert(L);
SLNode* p = L->next;
if (p == NULL)
{
printf("L NULL!\n");
return;
}
L->next = p->next;
L->data--;
free(p);
}
删除链表头部节点。
c
void SLPopBack(SLNode* L)
{
assert(L);
SLNode* p = L->next;
if (p == NULL)
{
printf("L NULL!\n");
return;
}
SLNode* pre = p->next;
while (pre->next != NULL)
{
p = pre;
pre = p->next;
}
p->next = NULL;
L->data--;
free(pre);
}
删除链表尾部节点。
c
void SLPopN(SLNode* L, int n)
{
assert(L);
if (L->next == NULL)
{
printf("L NULL!\n");
return;
}
if (n > L->data)
{
printf("n超过了SList长度\n");
return;
}
else if (n == 0)
{
SLPopFront(L);
return;
}
else if (n < 0)
{
printf("n < 0\n");
return;
}
SLNode* p = L->next;
SLNode* pre = p->next;
for (int i = 1; i < n; i++)
{
p = pre;
pre = pre->next;
}
p->next = pre->next;
L->data--;
free(pre);
}
删除指定位置后的节点,包括边界条件检查。
数据查找和修改
c
int Compare(Etype x, Etype y)
{
return x == y;
}
int SLFind(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
int num = 0;
while (num < L->data)
{
num++;
if (Compare(p->data, x))
return num;
p = p->next;
}
return -1;
}
查找特定值在链表中的位置。
c
void SLModify(SLNode* L, Etype x, int n)
{
assert(L);
if (L->data < n)
{
printf("n超过了SList长度\n");
return;
}
if (L->next == NULL)
{
printf("L NULL!\n");
return;
}
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
SLNode* pre = p->next;
if (n == 1)
{
L->next = q;
q->next = p->next;
return;
}
else if(n < 1)
{
printf("n < 1\n");
return;
}
for (int i = 2; i < n; i++)
{
p = pre;
pre = pre->next;
}
p->next = q;
q->next = pre->next;
free(pre);
}
修改链表中指定位置的节点值。
特殊操作
c
SLNode* SLReEy(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
SLNode* prv = L;
SLNode* pre = p->next;
int num = 0;
while (1)
{
if (Compare(p->data, x))
{
prv->next = pre;
free(p);
p = pre;
if (pre == NULL)
break;
pre = pre->next;
continue;
}
num++;
prv = prv->next;
p = pre;
if (pre == NULL)
break;
pre = pre->next;
}
L->data = num;
}
删除链表中所有包含特定值的节点。
c
void SLNewHand(SLNode* L)
{
assert(L);
if (L->next == NULL)
return;
SLNode* p = L->next;
SLNode* pre = p->next;
SLNode* prv = NULL;
while(1)
{
p->next = prv;
prv = p;
if (pre == NULL)
break;
p = pre;
pre = pre->next;
}
L->next = p;
}
反转链表顺序。
完整代码
SList.c
cpp
#include"SList.h"
//创建链表项
SLNode* SLBuNode(Etype x)
{
SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
if (newnode == NULL)
{
perror("Malloc");
exit(1);
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//创建头指针
void SLHandInit(SLNode* L)
{
assert(L);
L->data = 0;
L->next = NULL;
}
//销毁单链表
void SLDestroy(SLNode* L)
{
assert(L);
SLNode* p = L->next;
while (p != NULL)
{
SLNode* temp = p;
p = p->next;
free(temp);
}
L->next = NULL;
L->data = 0;
}
//打印单链表
void SLPrint(SLNode* L)
{
assert(L);
SLNode* p = L->next;
while (p != NULL)
{
printf("%d->", p->data);
p = p->next;
}
printf("NULL\n");
}
//头插插入数据
void SLPushFront(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
q->next = p;
L->next = q;
L->data++;
}
//尾插插入数据
void SLPushBack(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
if (L->next == NULL)
{
L->next = q;
}
else
{
while (p->next != NULL)
{
p = p->next;
}
p->next = q;
}
L->data++;
}
//头插删除数据
void SLPopFront(SLNode* L)
{
assert(L);
SLNode* p = L->next;
if (p == NULL)
{
printf("L NULL!\n");
return;
}
L->next = p->next;
L->data--;
free(p);
}
//尾插删除数据
void SLPopBack(SLNode* L)
{
assert(L);
SLNode* p = L->next;
if (p == NULL)
{
printf("L NULL!\n");
return;
}
SLNode* pre = p->next;
while (pre->next != NULL)
{
p = pre;
pre = p->next;
}
p->next = NULL;
L->data--;
free(pre);
}
//在SList的第n位之后添加数据
void SLPushN(SLNode* L, Etype x , int n)
{
assert(L);
if (L->next == NULL)
{
printf("L NULL!\n");
return;
}
if (n > L->data)
{
printf("n超过了SList长度\n");
return;
}
else if (n == 0)
{
SLPushFront(L, x);
return;
}
else if (n < 0)
{
printf("n < 0\n");
return;
}
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
SLNode* pre = p->next;
for (int i = 1; i < n; i++)
{
p = pre;
pre = pre->next;
}
p->next = q;
q->next = pre;
L->data++;
}
//删除SList上第n位之后的数据
void SLPopN(SLNode* L, int n)
{
assert(L);
if (L->next == NULL)
{
printf("L NULL!\n");
return;
}
if (n > L->data)
{
printf("n超过了SList长度\n");
return;
}
else if (n == 0)
{
SLPopFront(L);
return;
}
else if (n < 0)
{
printf("n < 0\n");
return;
}
SLNode* p = L->next;
SLNode* pre = p->next;
for (int i = 1; i < n; i++)
{
p = pre;
pre = pre->next;
}
p->next = pre->next;
L->data--;
free(pre);
}
//比较两个Etype类型数据是否相同
int Compare(Etype x, Etype y)
{
return x == y;
}
//查找SList上数据位置
int SLFind(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
int num = 0;
while (num < L->data)
{
num++;
if (Compare(p->data, x))
return num;
p = p->next;
}
return -1;
}
//修改SList上第n位数据
void SLModify(SLNode* L, Etype x, int n)
{
assert(L);
if (L->data < n)
{
printf("n超过了SList长度\n");
return;
}
if (L->next == NULL)
{
printf("L NULL!\n");
return;
}
SLNode* p = L->next;
SLNode* q = SLBuNode(x);
SLNode* pre = p->next;
if (n == 1)
{
L->next = q;
q->next = p->next;
return;
}
else if(n < 1)
{
printf("n < 1\n");
return;
}
for (int i = 2; i < n; i++)
{
p = pre;
pre = pre->next;
}
p->next = q;
q->next = pre->next;
free(pre);
}
//去除SList上的所有x
SLNode* SLReEy(SLNode* L, Etype x)
{
assert(L);
SLNode* p = L->next;
SLNode* prv = L;
SLNode* pre = p->next;
int num = 0;
while (1)
{
if (Compare(p->data, x))
{
prv->next = pre;
free(p);
p = pre;
if (pre == NULL)
break;
pre = pre->next;
continue;
}
num++;
prv = prv->next;
p = pre;
if (pre == NULL)
break;
pre = pre->next;
}
L->data = num;
}
//反转SList
void SLNewHand(SLNode* L)
{
assert(L);
if (L->next == NULL)
return;
SLNode* p = L->next;
SLNode* pre = p->next;
SLNode* prv = NULL;
while(1)
{
p->next = prv;
prv = p;
if (pre == NULL)
break;
p = pre;
pre = pre->next;
}
L->next = p;
}
SList.h
cpp
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define MAX 100
typedef int Etype;
struct SListNode
{
Etype data;
struct SListNode* next; //指向下一个节点的指针
};
typedef struct SListNode SLNode;
void SLHandInit(SLNode* L);//创建头指针
void SLDestroy(SLNode* L);//销毁单链表
SLNode* SLBuNode(Etype x);//创建链表项
void SLPushFront(SLNode* L, Etype x);//头插插入数据
void SLPushBack(SLNode* L, Etype x);//尾插插入数据
void SLPushN(SLNode* L, Etype x, int n);//在SList的第n位之后添加数据
void SLPopFront(SLNode* L);//头插删除数据
void SLPopBack(SLNode* L);//尾插删除数据
void SLPopN(SLNode* L, int n);//删除SList上第n位的数据
int Compare(Etype x, Etype y);//比较两个Etype类型数据是否相同
int SLFind(SLNode* L, Etype x);//查找SList上数据位置
void SLModify(SLNode* L, Etype x, int n);//修改SList上第n位数据
SLNode* SLReEy(SLNode* L, Etype x);//去除SList上的所有x
void SLNewHand(SLNode* L);//反转SList
void SLPrint(SLNode* L);//打印单链表
测试代码
test.c
cpp
#include "SList.h"
void test()
{
//创建指针
SLNode L;
SLHandInit(&L);
printf("1.尾插法在SList中添加数据:\t");
//尾插法添加数据
SLPushBack(&L, 1);
SLPushBack(&L, 2);
SLPushBack(&L, 3);
SLPushBack(&L, 4);
SLPushBack(&L, 5);
//输出单链表
SLPrint(&L);
printf("\n");
printf("2.头插法在SList中添加数据:\t");
//头插法添加数据
SLPushFront(&L, 1);
SLPushFront(&L, 2);
SLPushFront(&L, 3);
SLPushFront(&L, 4);
SLPushFront(&L, 5);
//输出单链表
SLPrint(&L);
printf("\n");
printf("3.头插法删除SList中数据:\t");
//头删
SLPopFront(&L);
SLPopFront(&L);
SLPopFront(&L);
//输出单链表
SLPrint(&L);
printf("\n");
printf("4.尾插法删除SList中数据:\t");
//尾删
SLPopBack(&L);
SLPopBack(&L);
SLPopBack(&L);
//输出单链表
SLPrint(&L);
printf("\n");
printf("5.在SList的第n位之后添加数据:\t");
///在SList的第n位之后添加数据
SLPushN(&L, 9, 1);
SLPushN(&L, 9, 2);
SLPushN(&L, 9, 3);
//输出单链表
SLPrint(&L);
printf("\n");
printf("6.删除SList上第n位之后的数据:\t");
//删除SList上第n位的数据
SLPopN(&L, 1);
SLPopN(&L, 2);
SLPopN(&L, 3);
//输出单链表
SLPrint(&L);
printf("\n");
printf("7.在SList上查找数据位置:\t");
//查找SList上数据位置
int a = SLFind(&L, 9);
int b = SLFind(&L, 1);
int c = SLFind(&L, 2);
printf("%d %d %d\n", a, b, c);
printf("\n");
printf("8.在SList上修改第n位数据:\t");
//修改SList上第n位数据
SLModify(&L, 8, a);
SLModify(&L, 8, b);
SLModify(&L, 8, c);
//输出单链表
SLPrint(&L);
printf("\n");
printf("9.去除SList上的所有与x相等数据:\t");
//去除SList上的所有x
SLReEy(&L, 8);
//输出单链表
SLPrint(&L);
printf("\n");
printf("现在SList上所存剩余数据量为:\t%d\n", L.data);
printf("\n");
printf("11.尾插法重新在SList中添加数据:\t");
//尾插法添加数据
SLPushBack(&L, 1);
SLPushBack(&L, 2);
SLPushBack(&L, 3);
SLPushBack(&L, 4);
SLPushBack(&L, 5);
//输出单链表
SLPrint(&L);
printf("\n");
printf("反转NList中的全部数据数据:\t");
//反转SList
SLNewHand(&L);
//输出单链表
SLPrint(&L);
//销毁指针
SLDestroy(&L);
}
int main()
{
test();
return 0;
}
该实现覆盖了单链表的基本操作,结构清晰,适合作为基础数据结构的教学示例。