文章目录
1. 链表的概念及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,下一章我们代码实现了就知道了。
2单链表的实现
2.1新节点的创建
SLTNode* BuySTLNode(x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
perror("SLTpushback::malloc");
return NULL;
}
newnode->date = x;
newnode->next = NULL;
return newnode;
}
2.2单链表尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = BuySTLNode(x);
//找尾
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
2.3单链表尾删
void SLTPopback(SLTNode** pphead)
{
assert(pphead);
//链表为空
assert(*pphead);
//1.只有一个节点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//2.多个节点
else
{
SLTNode* tail = *pphead;
SLTNode* prev = NULL;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
2.4单链表头插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = BuySTLNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
2.5单链表头删
void SLTPopFront(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);
SLTNode* tail = *pphead;
*pphead = (*pphead)->next;
free(tail);
tail = NULL;
}
2.6单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->date == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
2.7在pos前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
assert(pphead);
assert(pos);
if (*pphead == pos)
{
SLTPushFront(pphead, x);
}
SLTNode* newnode = BuySTLNode(x);
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = newnode;
newnode->next = pos;
}
2.8删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead);
assert(*pphead);
if (*pphead == pos)
{
SLTPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
}
}
2.9单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
assert(pos);
SLTNode* newnode = BuySTLNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
2.10单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos)
{
assert(pos);
assert(pos->next);
SLTNode* cur = pos->next;
pos->next = cur->next;
free(cur);
cur = NULL;
}
2.11单链表的销毁
void SListDestroy(SLTNode* phead)
{
SLTNode* prev = NULL;
while (phead)
{
prev = phead;
phead = phead->next;
free(prev);
prev = NULL;
}
}
3.源代码
3.1 SList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType date;
struct SListNode* next;
}SLTNode;
//单链表打印
void SLTPrint(SLTNode* phead);
//单链表尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);
//void SLTPushBack(SLTNode* phead, SLTDateType x);
//单链表头插
void SLTPushFront(SLTNode** pphead, SLTDateType x);
//单链表尾删
void SLTPopback(SLTNode** pphead);
//单链表头删
void SLTPopFront(SLTNode** pphead);
//单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x);
//在pos前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);
//删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos);
// 单链表的销毁
void SListDestroy(SLTNode* phead);
// 单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos);
3.2 SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
//打印
void SLTPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur)
{
printf("%d->", cur->date);
cur = cur->next;
}
printf("NULL\n");
}
//新节点
SLTNode* BuySTLNode(x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
perror("SLTpushback::malloc");
return NULL;
}
newnode->date = x;
newnode->next = NULL;
return newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = BuySTLNode(x);
//找尾
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
//void SLTPushBack(SLTNode* phead, SLTDateType x)
//{
// SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
// if (newnode == NULL)
// {
// perror("SLTpushback::malloc");
// return;
// }
// newnode->date = x;
// newnode->next = NULL;
// //找尾
// if (phead == NULL)
// {
// phead = newnode;
// }
// else
// {
// SLTNode* tail = phead;
// while (tail->next != NULL)
// {
// tail = tail->next;
// }
// tail->next = newnode;
// }
//}
//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = BuySTLNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
//尾删
void SLTPopback(SLTNode** pphead)
{
assert(pphead);
//链表为空
assert(*pphead);
//1.只有一个节点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//2.多个节点
else
{
SLTNode* tail = *pphead;
SLTNode* prev = NULL;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
//SLTNode* tail = *pphead;
//while (tail->next->next != NULL)
//{
// tail = tail->next;
//}
//free(tail->next);
//tail->next = NULL;
}
}
//头删
void SLTPopFront(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);
SLTNode* tail = *pphead;
*pphead = (*pphead)->next;
free(tail);
tail = NULL;
}
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x)
{
SLTNode* cur = phead;
while (cur)
{
if (cur->date == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
//在pos前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
assert(pphead);
assert(pos);
if (*pphead == pos)
{
SLTPushFront(pphead, x);
}
SLTNode* newnode = BuySTLNode(x);
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = newnode;
newnode->next = pos;
}
//删除pos前位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead);
assert(*pphead);
if (*pphead == pos)
{
SLTPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
}
}
// 单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
assert(pos);
SLTNode* newnode = BuySTLNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos)
{
assert(pos);
assert(pos->next);
SLTNode* cur = pos->next;
pos->next = cur->next;
free(cur);
cur = NULL;
}
// 单链表的销毁
void SListDestroy(SLTNode* phead)
{
SLTNode* prev = NULL;
while (phead)
{
prev = phead;
phead = phead->next;
free(prev);
prev = NULL;
}
}
3.3 test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void TestList1()
{
SLTNode* plist = NULL;
SLTPushBack(&plist, 1);
SLTPushBack(&plist, 2);
SLTPushBack(&plist, 3);
SLTPushBack(&plist, 4);
SLTPrint(plist);
//SLTNode s;
//SLTPushBack(&s, 1);
//SLTPushBack(&s, 2);
//SLTPushBack(&s, 3);
//SLTPushBack(&s, 4);
//SLTPrint(&s);
SLTNode* pos = SLTFind(plist, 3);
if (pos)
{
SLTInsert(&plist, pos, 20);
}
SLTPrint(plist);
}
void TestList2()
{
SLTNode* plist = NULL;
SLTPushFront(&plist, 1);
SLTPushFront(&plist, 2);
SLTPushFront(&plist, 3);
SLTPushFront(&plist, 4);
SLTPrint(plist);
SLTPopback(&plist);
SLTPrint(plist);
SLTPopback(&plist);
SLTPrint(plist);
SLTPopback(&plist);
SLTPrint(plist);
SLTPopback(&plist);
SLTPrint(plist);
}
void TestList3()
{
SLTNode* plist = NULL;
SLTPushFront(&plist, 1);
SLTPushFront(&plist, 2);
SLTPushFront(&plist, 3);
SLTPushFront(&plist, 4);
SLTPrint(plist);
SLTPopFront(&plist);
SLTPrint(plist);
SLTPopFront(&plist);
SLTPrint(plist);
SLTPopFront(&plist);
SLTPrint(plist);
SLTPopFront(&plist);
SLTPrint(plist);
}
void TestList4()
{
SLTNode* plist = NULL;
SLTPushBack(&plist, 1);
SLTPushBack(&plist, 2);
SLTPushBack(&plist, 3);
SLTPushBack(&plist, 4);
SLTPrint(plist);
SLTNode* pos = SLTFind(plist, 3);
if (pos)
{
SListEraseAfter(pos);
}
SLTPrint(plist);
pos = SLTFind(plist, 2);
if (pos)
{
SListEraseAfter(pos);
}
SLTPrint(plist);
pos = SLTFind(plist, 1);
if (pos)
{
SListEraseAfter(pos);
}
SLTPrint(plist);
//pos = SLTFind(plist, 1);
//if (pos)
//{
// SLTErase(&plist, pos);
//}
//SLTPrint(plist);
//pos = SLTFind(plist, 2);
//if (pos)
//{
// SLTErase(&plist, pos);
//}
//SLTPrint(plist);
//pos = SLTFind(plist, 4);
//if (pos)
//{
// SLTErase(&plist, pos);
//}
//SLTPrint(plist);
SListDestroy(plist);
}
int main()
{
//TestList1();
//TestList2();
//TestList3();
TestList4();
return 0;
}