【数据结构】 模拟实现单链表(C语言)
- 引言:单链表作为数据结构中非常重要的链式存取结构因为其支持尾插尾删,头插头删,且支持任意位置插入删除的优良特性被广泛应用于许多场景,当然也在面试和笔试中常常被点击。它在物理存储结构上非连续、非顺序,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
定义(两种):
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表,另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而较为简单了。
逻辑图如下:
注:在现实中我们最常用到的还是以下两种结构的单链表,今天我们要实现的就是无头单向不循环链表。
代码实现如下:
SList.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType _data;
struct SListNode* _next;
}SListNode;
typedef struct SList
{
SListNode* _head;
}SList;
void SListInit(SList* plt);//初始化
void SListDestory(SList* plt);//
SListNode* BuySList(SLTDataType x);
void SListPushFront(SList* plt, SLTDataType x);//头插
void SListPopfront(SList* plt);//头删
void SListPushBack(SList* plt, SLTDataType x);
void SListPopBack(SList*plt);
SListNode* SListFind(SList* plt, SLTDataType x);
//在pos后插入
void SListInsertAfter(SListNode* pos, SLTDataType x);
//在pos前面插入
void SListEraseAfter(SListNode* pos);
void SListNodeRemove(SList*plt, SLTDataType x);
void SListPrint(SList* plt);
void TestSList();
SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void SListInit(SList* plt)
{
assert(plt);
plt->_head = NULL;
}
void SListNode* BuySList(SLTDataType x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->_data = x;
newnode->_next = NULL;
}
void SListPushFront(SList* plt, SLTDataType x)//头插
{
assert(plt);
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->_data = x;
newnode->_next = NULL;
newnode ->_next = plt->_head;
plt->_head = newnode;
}
void SListPopfront(SList* plt)//头删
{
assert(plt);
if (plt->_head == NULL)
{
return;
}
else
{
SListNode* cur = plt->_head;
plt->_head = cur->_next;
free(cur);
cur = NULL;
}
}
void SListPushBack(SList* plt, SLTDataType x)//尾插
{
assert(plt);
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->_data = x;
newnode->_next = NULL;
//1.空
//2.非空
if (plt->_head == NULL)
{
plt->_head = newnode;
}
else
{
SListNode* cur = plt->_head;
//找尾
while (cur->_next != NULL)
{
cur = cur->_next;
}
cur->_next=newnode;
}
}
void SListPopBack(SList*plt)//尾删
{
assert(plt);
SListNode* cur = plt->_head;
if (cur == NULL)
{
return;
}
else if (cur->_next==NULL)
{
free(cur);
plt->_head = NULL;
}
else
{
while (cur->_next->_next != NULL)
{
cur = cur->_next;
}
free(cur->_next);
cur->_next = NULL;
}
}
SListNode* SListFind(SList* plt, SLTDataType x)//查找x
{
assert(plt);
SListNode* cur = plt->_head;
while (cur!=NULL)
{
if (cur->_data == x)
{
//printf("找到了\n");
return cur;
}
cur = cur->_next;
}
return NULL;
}
void SListInsertAfter(SListNode* pos, SLTDataType x)
{
assert(pos);
SListNode* cur = pos->_next;
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->_data = x;
newnode->_next = NULL;
newnode->_next = cur;
pos->_next=newnode;
}
void SListNodeRemove(SList*plt, SLTDataType x)
{
assert(plt);
SListNode* prev=NULL;
SListNode* cur = plt->_head;
while (cur != NULL)
{
if (cur->_data==x)
{
if (prev == NULL)
{
plt->_head = cur->_next;//1,2(删除1时,prevent为空)
}
else
{
prev->_next = cur->_next;
}
free(cur);
cur = NULL;
return;
}
else
{
prev = cur;
cur = cur->_next;
}
}
}
void SListEraseAfter(SListNode* pos)
{
if (pos->_next == NULL)
{
return NULL;
}
else
{
SListNode* next = pos->_next;
pos->_next = next->_next;
free(next);
next = NULL;
}
}
void SListPrint(SList* plt)
{
assert(plt);
SListNode* cur = plt->_head;
while (cur != NULL)
{
printf("%d->", cur->_data);
cur = cur->_next;
}
printf("NULL\n");
}
void TestSList()
{
SList lt;
SListInit(<);
SListPushFront(<, 3);
SListPushFront(<, 2);
SListPushFront(<, 1);
SListPushFront(<, 0);
SListPrint(<);
SListPopfront(<, 3);
SListPrint(<);
SListPushBack(<, 4);
SListPrint(<);
SListNode* pos = SListFind(<, 2);
SListPopBack(<);
SListPrint(<);
SListEraseAfter(<);
SListPrint(<);
SListNodeRemove(<, 2);
SListPrint(<);
SListInsertAfter(pos, 5);
SListPrint(<);
}
Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
int main()
{
TestSList();
system("pause");
return 0;
}