这两天对单双链表一系列操作的学习

首先一开始是复习了一下指针和结构体的概念,简单来说指针就是储存地址

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。

  1. 删除倒数第几个节点
  2. 把两个升序的链表合并成一个升序的链表

哈哈,这两个题目最初我写了一个多小时,兄弟们可以去康康qaq~~ 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值