首先一开始是复习了一下指针和结构体的概念,简单来说指针就是储存地址
int main(){
int a=10;、、定义一个a的值
int *p;
p=&a;//这里p指向了a值的地址
cout << *p ;//这里就等于a值
}
结构体:
链表的实现离不开一个结构体
struct node {
int val;
struct node *next;
};
还有一个不能缺少的就是动态分配内存malloc,我们申请了空间之后就要一个指针指向这个空间,就是储存这个空间的地址。
int *p;
p=(int *)malloc(sizeof(int));//这样p所指向的就是我们刚申请的这块空间
Ps:用malloc得加上个头函数stdlib.h 嘻嘻嘻,我自己写的时候就给忘了。
好,现在准备工作基本上就结束了,下面就手敲一个单链表,
#include <iostream>
#include <stdlib.h>
using namespace std;
struct node{
int date;
struct node *next;
};//这里是我们需要的结构体
int main(int argc, char** argv) {
struct node *head;
head=NULL;//这里的头指针我们先把他设置为空值
struct node *p,*q,*t;
int a;
//这里循环读入十个数字
for(int i=0;i<9;i++){
cin >> a;
p=(struct node*)malloc(sizeof(struct node));//为p分配一个空间用来存放当前的节点
p->date=a;
p->next=NULL;//p来指向这个节点,并把数据存放到这个指针中,next指针设为空值
if(head==NULL){
head=p;//如果是第一个节点那就让头指针指向p
}else{
q->next=p;//把上一个的next指针指向当前的节点
}
q=p;//q指向当前的节点
}
这样我们就算是建立了一个链表,并往里面读入了9个数字,下面是个人的对于链表的解释,绘图能力有限hhh,也许不怎么能让别人看懂。在上面的链表建立中,我们用的是让上一个节点的next指向当前节点。
下面我们来遍历整个链表,上面我们说了最后一个节点的next值是NULL,我们就从这里入手,当某个节点的next为NULL,我们就知道这个链表遍历结束了。
//接上一段代码hhh
t=head;
while(t!=NULL){
cout << t->date << endl;
t=t->next;//输出当前节点的值,并继续到下一个节点,直到next为NULL结束
}
好,到这里一个链表的输出就基本OK了(喝口水,吃袋辣条,下面重点来了)。
和链表相对应差不多的还有一个东西叫数组,相比较而言,数组方便读取,链表的优点就是在与对于各节点元素的插入和删除。
这里对插入的图解将就看看hhhh,水平有限qwq。
根据上面的思路,我们直接来干一个插入。
//这里继续接上面的代码
t=head;//这里我们指向链表的头部节点
int x;
cin >> x;//要插入的数,哦对了,我们假设我们上面建的链表的是个递增的链表
while(t!=NULL){
//当前节点的下一节点的数据如果大于要插入的数,那这个数就应该插入在当前节点和下一节点中。
if(t->next->date > x){
//老规矩,先申请一个空间来存放新增的节点
p=(struct node*)malloc(sizeof(struct node));
p->date=x;
p->next=t->next;//新增节点的next所指的就是原来节点的下一个节点
t->next=p;//当前节点的next指向新增的节点
break;//插入完成跳出循环
}
t=t->next;//到下一个节点
}
如果我们把上面的插入能搞明白了,那删除肯定稳稳能拿捏住了。
这是对删除节点的图解qwq
//继续接上面的代码hhh
//实现删除掉比n大的第一个节点值
t=head;
int n;
cin >> n;//输入要比较的值
while(t!=NULL){
//如果当前节点的下一个节点值比n大,我们就把下一个节点给删除掉
if(t->next->date >n){
t->next=t->next->next;//把当前节点的next直接指向下下个节点
break;
}
t=t->next;//到下一个节点
}//删除一个结点
到这里单链表的基本操作就结束了,但是我们在单链表中有一个问题,单链表是一个一个的读取下一个节点值,而且是有固定的顺序从头节点慢慢的到最后。好,为了解决这个问题就要隆重推出双向链表,顾名思义,可以从前到后也可以从后到前,只要在结构体中加入一个向前的节点来存储前一个节点。
struct node {
int date;
struct node *next;
struct node *front;
};
好,老规矩我们先建立一个双向链表。
int main(){
struct node *head,*p,*q,*r;
head=NULL;
for(int i=0;i<9;i++){
int t;
cin >> t;
p=(struct node *)malloc(sizeof(struct node));
p->date=t;
p->front=NULL;
p->next=NULL;
if(head==NULL){
head=p;
}else{
q->next=p;//把上一个节点的next值指向当前节点
p->front=q;//与单链表不同的是,把当前节点的front值指向上一个节点q
}
q=p;//让q往下进一个节点
}//双向链表的建立
哈哈,和单链表基本上一样,就是多了一个可以遍历的方向,双向链表的插入和删除也基本上和单链表相同。
下面由于手敲的太累,直接贴上完成插入删除的代码,基本上只要理解的单链表,双向链表问题不大qwq。
struct node {
int date;
struct node *next;
struct node *front;
};
int main(){
struct node *head,*p,*q,*r;
head=NULL;
for(int i=0;i<9;i++){
int t;
cin >> t;
p=(struct node *)malloc(sizeof(struct node));
p->date=t;
p->front=NULL;
p->next=NULL;
if(head==NULL){
head=p;
}else{
q->next=p;
p->front=q;
}
q=p;
}//双向链表的建立
r=q;
int x;
cin >> x;
while(r!=NULL){
if(r->front->date < x){
p=(struct node *)malloc(sizeof(struct node));
p->date=x;
p->front= r->front;
p->next=r;
r->front->next=p;
r->front=p;
break;
}
r=r->front;
}//双链表的增加
r=q;
int y;
cin >> y;
while(r!=NULL){
if(r->front->date < y){
r->front=r->front->front;
//r->front->front->next=r;
break;
}
r=r->front;
}//删除一个节点
r=q;
while(r!=NULL){
cout << r->date << " ";
r=r->front;
}//遍历链表
return 0;
}
这里给出一组例子
先输入20,把他按顺序插入进去,然后找到第一个比15小的值把他删除掉qwq
双向链表,拿捏。hhhhh
然鹅,我发现学会了这些对于链表而言就是九牛一毛,在leetcode上写了一个个简单和一个中等的题,有兴趣大家也可以写一些hhh。
哈哈,这两个题目最初我写了一个多小时,兄弟们可以去康康qaq~~