接下来给大家理一下链表思路。
1.逻辑结构
可以看出,与顺序表不同,链表是像链条一样一个一个连在一起,在这里我们用指针来实现。
2.逻辑结构我们不好理解,我们来用物理结构给大家展示
上一个结构体存下一个地址,下一个再存下下一个,链式环环相扣。
typedef int StdDatatype; //为了我们以后可以存储其他类型的链表,我们将数据类型typedef一下。
struct StdlistNode
{
StdDatatype data; //存储这个数据
struct StdlistNode* Next; //相当于箭头指向下一个数据的结构体
};
typedef struct StdlistNode STDNode; //将结构体的名字重定义一下
void PrintStlist(STDNode* plist) //打印链表
{
STDNode* tail = plist;
while (tail != NULL)
{
printf("%d->", tail->data);
tail = tail->Next;
}
printf("NULL");
}
STDNode* Buymemory(StdDatatype x)
{
STDNode* now = (STDNode*)malloc(sizeof(StdDatatype));
now->data = x;
now->Next = NULL;
return now;
}
void StdlistPushFront(STDNode** plist, StdDatatype x)
{
STDNode* now = Buymemory(x); //开辟一块空间 里面存储x
now->Next = *plist; //将NEXT的地址和链表连接起来。
*plist = now; //将新的链表赋值给之前的链表完成头插
}
尾插比头插相对来说复杂一点,首先我们需要先找到最后一个链表,之后再插入数据
void StdlistPushBack(STDNode** plist, StdDatatype x)
{
STDNode* now = Buymemory(x);
if (*plist == NULL) //如果链表中没有元素,则直接赋值即可
{
*plist = now;
}
else
{
STDNode* tail = *plist;
while (tail->Next != NULL) //寻找尾部元素
{
tail = tail->Next;
}
tail->Next = now; //找到后将链表赋值给尾部的下一个结构
}
}
注意VS2019中free释放空间需要写成void形式。
void StdlistPopFront(STDNode** plist)
{
if (*plist == NULL) //如果链表为空,直接结束
return;
if ((*plist)->Next == NULL) //判断如果链表只有一个元素
{
STDNode* mid = (*plist)->Next; //引入中间结构体,存储下一块
void free(void* mid); //将下一块NULL内存删除
*plist = NULL; //将头部置为空
}
else //正常情况下
{
STDNode* mid = (*plist)->Next; //引入中间变量存储下一块内存单元
void free(void* plist); //释放头部内存
*plist = mid; //将中间变量赋值给链表。
}
}
尾删相对来说就比较简单,我们只需要找到尾部将下一个NULL释放掉,然后将尾部赋值为NULL。
void StdlistPopBack(STDNode** plist) //尾删
{
if (*plist == NULL)//如果为空链表直接返回
return;
if ((*plist)->Next == NULL) //如果链表只有一个元素。
{
STDNode* mid = (*plist)->Next;//将下一块NULL释放,然后将第一块赋值为NULL
void free(void* mid);
*plist = NULL;
}
else //正常情况下
{
STDNode* mid = NULL;
STDNode* tail = *plist;
while (tail->Next != NULL) //寻找尾部元素
{
mid = tail;
tail = tail->Next;
}
void free(void* tail); //找到后释放NEXT NULL
mid->Next = NULL; //将尾部元素赋值为NULL
}
}
STDNode* StdlistFind(STDNode* plist, StdDatatype x) //寻找某元素
{
STDNode* Pop = plist;
while (Pop->data != x&&Pop->Next !=NULL) //寻找,如果不是一直往下走
{
Pop = Pop->Next;
}
if (Pop->data == x) //如果找到了则返回目标元素
return Pop;
else //找不到则返回NULL
return NULL;
}
void StdlistInsert(STDNode** plist, STDNode* Pop, StdDatatype x)
{
if (*plist == Pop) //如果首元素就是Pop,则相当于头插
{
StdlistPushFront(plist, x);
}
else //正常情况下
{
STDNode* now = Buymemory(x); //拓展一个内存空间存储x
STDNode* mid = *plist; //引入中间链表
while (mid->Next != Pop) 寻找元素
{
mid = mid->Next;
}
mid->Next = now; //将上一个元素的Next与now链接
now->Next = Pop; //将now的next与下一个链表链接
}
}
void StdlistErase(STDNode** plist, STDNode* Pop, StdDatatype x)
{
STDNode* now = Buymemory(x); //开辟一块空间存储x
STDNode* mid = *plist;
while (mid != Pop) //寻找Pop
{
mid = mid->Next;
}
if (mid->Next == NULL) //找到后如果Pop为最后一个元素直接尾插即可
{
StdlistPushBack(plist, x);
}
else //正常情况下
{
STDNode* tail = mid->Next;
mid->Next = now;
now->Next = tail;
}
}
#pragma once
#define _CRT_SECURE_NO_WAR
#include
#include
typedef int StdDatatype;
struct StdlistNode
{
StdDatatype data;
struct StdlistNode* Next;
};
typedef struct StdlistNode STDNode;
void StdlistPushBack(STDNode** plist, StdDatatype x); //尾插
void PrintStlist(STDNode* plist); //打印
void StdlistPushFront(STDNode** plist, StdDatatype x); //头插
void StdlistPopFront(STDNode** plist); //头删
void StdlistPopBack(STDNode** plist); //尾删
void StdlistInsert(STDNode** plist, StdDatatype x); //前插
void StdlistErase(STDNode** plist, StdDatatype x); //后插
STDNode* StdlistFind(STDNode* plist, StdDatatype x); //查找
#include "Slist.h"
void PrintStlist(STDNode* plist) //打印链表
{
STDNode* tail = plist;
while (tail != NULL)
{
printf("%d->", tail->data);
tail = tail->Next;
}
printf("NULL");
}
void StdlistPushFront(STDNode** plist, StdDatatype x) //头插
{
STDNode* now = Buymemory(x);
now->Next = *plist;
*plist = now;
}
void StdlistPushBack(STDNode** plist, StdDatatype x) //尾插
{
STDNode* now = Buymemory(x);
if (*plist == NULL)
{
*plist = now;
}
else
{
STDNode* tail = *plist;
while (tail->Next != NULL)
{
tail = tail->Next;
}
tail->Next = now;
}
}
void StdlistPopFront(STDNode** plist) //头删
{
if (*plist == NULL)
return;
if ((*plist)->Next == NULL)
{
STDNode* mid = (*plist)->Next;
void free(void* mid);
*plist = NULL;
}
else
{
STDNode* mid = (*plist)->Next;
void free(void* plist);
*plist = mid;
}
}
void StdlistPopBack(STDNode** plist) //尾删
{
if (*plist == NULL)
return;
if ((*plist)->Next == NULL)
{
STDNode* mid = (*plist)->Next;
void free(void* mid);
*plist = NULL;
}
else
{
STDNode* mid = NULL;
STDNode* tail = *plist;
while (tail->Next != NULL)
{
mid = tail;
tail = tail->Next;
}
void free(void* tail);
mid->Next = NULL;
}
}
STDNode* StdlistFind(STDNode* plist, StdDatatype x) //寻找某元素
{
STDNode* Pop = plist;
while (Pop->data != x&&Pop->Next !=NULL)
{
Pop = Pop->Next;
}
if (Pop->data == x)
return Pop;
else
return NULL;
}
void StdlistInsert(STDNode** plist, STDNode* Pop, StdDatatype x) //Pop的前方插入x
{
if (*plist == Pop)
{
StdlistPushFront(plist, x);
}
else
{
STDNode* now = Buymemory(x);
STDNode* mid = *plist;
while (mid->Next != Pop)
{
mid = mid->Next;
}
mid->Next = now;
now->Next = Pop;
}
}
void StdlistErase(STDNode** plist, STDNode* Pop, StdDatatype x)
{
STDNode* now = Buymemory(x);
STDNode* mid = *plist;
while (mid != Pop)
{
mid = mid->Next;
}
if (mid->Next == NULL)
{
StdlistPushBack(plist, x);
}
else
{
STDNode* tail = mid->Next;
mid->Next = now;
now->Next = tail;
}
}
#include "Slist.h"
void TextSlist()
{
STDNode* plist = NULL;
StdlistPushFront(&plist, 0);
StdlistPushBack(&plist, 1);
StdlistPushBack(&plist, 2);
StdlistPushBack(&plist, 3);
StdlistPushBack(&plist, 4);
StdlistPushBack(&plist, 5);
StdlistPushBack(&plist, 6);
/*StdlistPopFront(&plist);
StdlistPopBack(&plist);*/
/*STDNode* Pop = StdlistFind(plist, 6);*/
/*StdlistInsert(&plist, Pop,30);*/
STDNode* Pop = StdlistFind(plist, 6);
StdlistErase(&plist, Pop, 30);
PrintStlist(plist);
}
int main()
{
TextSlist();
return 0;
}