前言
链表是一种比较基础的结构,用链表实现增删比数组方便许多只不过实现起来比数组困难那么今天我们就来看看链表如何实现。
链表与顺序表的比较
顺序表再存储的 时候其存储的空间是连续的的因此再开辟空间的时候往往都是一次性开辟多个空间那么这时候就会面对着空间的不足与浪费,并且我们会发现顺序表在实现删除的时候其时间复杂度为O(n)非常的不方便,而链表就避免了这个事情。
链表的实现
首先我们要知道一个链表应该实现的功能有哪些,其实无非就是增删查改打印这五个功能,那么我们先来认识一下链表的物理结构。
如图中所示链表是由节点构成的一个节点有两个部分一个是存储的值,另一个是指针,而这个指针所指向的其实就是下一个节点。因此连续起来的实际结构就是下图。
那么应该如何实现插入呢?这里给大家举一个题目,列如现在要插入一个新的节点叫做newnode插入到第一个和第二个节点之间我们应该怎么办呢?如图
第一步首先就是先让newnode指向第一个节点指向的内容
第二步骤就是让第一个节点指向newnode
其实这跟我们有时候插朋友队是一样的你想插朋友的队那你是不是得先站在你朋友的前面,之后呢这时候你朋友的前面是不是就变成了你啊。
代码实现
首先我们需要先设置头节点并且对头节点进行初始化也就是初始化链表。
代码如下
void indit(sl**head)
{
(*head)->next = NULL;
return;
}
int main()
{
sl* head = (sl*)malloc(sizeof(sl));
indit(&head);//初始化函数我们起名字为indit()。
return 0;
}
然后我们要实现插入函数这里呢我们可以将插入函数分为头插 尾插 任意部位插入我举一个尾插的例子其余的其实我们可以举一反三:
sl* check()
{
sl*Newnode = (sl*)malloc(sizeof(sl));
if(Newnode==NULL)//这里表示扩容失败
{
perror("malloc::faile");
}
return Newnode;
}
void push_back(sl** phead, type x)
{
sl* tair = (*phead);
sl* newnode = check();
newnode->x = x;
while (tair->next != NULL)
{
tair = tair->next;
}
newnode->next=tair->next;
tair->next = newnode;
}
int main()
{
sl* head = (sl*)malloc(sizeof(sl));
indit(&head);
push_back(&head, 1);
push_back(&head, 2);
push_back(&head, 3);
push_back(&head, 4);
push_back(&head, 4);
push_back(&head, 4);
popback(head, 4);
listprin(head);
return 0;
}
我们要插入一个新的节点那么首先第一步肯定是要把节点先创建出来,因此我们需要先malloc一个内存空间,之后呢由于我们是尾插因此我们需要先找到尾节点也就是用一个while循环进行遍历。找到尾节点从而将其插入。
删除
好的那么接下来我们来简述一下如何实现删除,这里呢其实跟我们现实也是一样的比如说你是饭店老板然后呢你发现有个人耍赖皮强行插队那么身为高贵,美丽,优雅,正义的你应该怎么办呢?直接把他赶走吗?当然不是啦直接动手的话是不是太粗鲁啊,因此最好的办法就是轮到他的时候我们给他后面那个人打饭直接无视他,这样子他不也是相当于被删除了吗对吧。好了上代码
void popback(sl*phead,type x)
{
sl* tair =phead;
sl* per = phead->next;
sl* pper = phead;
while (tair->next != NULL)
{
if (tair->next->x == x)
{
tair->next = tair->next->next;
}
else {
tair = tair->next;
}
}
while (per->next != NULL)
{
per = per->next;
pper = pper->next;
}
if (per->x == x)
{
pper->next = per->next;
}
}
这里呢由于我们要删除的元素可能不止一个所以我们用一个循环把所有不合格的全部删除就可以了。
打印函数
打印函数就比较简单了就是一个while循环遍历就可以了直接给各位上代码了
void listprin(sl* phead)
{
sl* tair = phead->next;
while (tair->next != NULL)
{
printf("%d->", tair->x);
tair = tair->next;
}
printf("%d", tair->x);
}
总结
总的代码我给各位拷贝出来
#include<iostream>
#include<Assert.h>
using namespace std;
typedef int type;
typedef struct list {
struct list *next;
type x;
}sl;
void indit(sl**head)
{
(*head)->next = NULL;
return;
}
sl* check()
{
sl*Newnode = (sl*)malloc(sizeof(sl));
return Newnode;
}
void push_back(sl** phead, type x)
{
sl* tair = (*phead);
sl* newnode = check();
newnode->x = x;
while (tair->next != NULL)
{
tair = tair->next;
}
newnode->next=tair->next;
tair->next = newnode;
}
void listprin(sl* phead)
{
sl* tair = phead->next;
while (tair->next != NULL)
{
printf("%d->", tair->x);
tair = tair->next;
}
printf("%d", tair->x);
}
void popback(sl*phead,type x)
{
sl* tair =phead;
sl* per = phead->next;
sl* pper = phead;
while (tair->next != NULL)
{
if (tair->next->x == x)
{
tair->next = tair->next->next;
}
else {
tair = tair->next;
}
}
while (per->next != NULL)
{
per = per->next;
pper = pper->next;
}
if (per->x == x)
{
pper->next = per->next;
}
}
sl* slfind(sl* phead,type x)
{
assert(phead);
sl* tair = phead;
while (tair->x == x)
{
return tair;
}
}
int main()
{
sl* head = (sl*)malloc(sizeof(sl));
indit(&head);
push_back(&head, 1);
push_back(&head, 2);
push_back(&head, 3);
push_back(&head, 4);
push_back(&head, 4);
push_back(&head, 4);
push_back(&head, 3);
popback(head, 4);
popback(head, 1);
listprin(head);
return 0;
}
代码最终实现的结果呢如图
如果各位有什么不理解的地方也可以直接把代码拷贝过去进行试验