双链表(C++)

1、双链表

在这里插入图片描述

输入样例:
10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2
输出样例:
8 7 7 3 2 9

1.1 初始化
//初始化
void init()
{
	//1表示右端点.0表示左端点
	r[0]=1,l[1]=0;

	//0和1已经用过了,所以当前指针idx从2开始
	idx=2;
}
1.2 插入的图解

在第k点的右边插入一个数x
在这里插入图片描述

线条表示:
圈1表示:旧的r[k]2表示:l[k+1]3表示:新的l[k+1]4表示:创建的r[idx]5表示:新的r[k]6表示:创建的l[idx] 

插入的过程:
圈1改为圈6,但此时圈1还在,没有被覆盖掉
创建圈41+3,这个过程中将圈2覆盖掉,即圈2被删掉了
覆盖掉圈1相当于删除圈1,并添加圈5
1.3 插入代码表示
//在第k点的右边插入一个数x
void add(int k,int x)
{
	e[idx]=x;//将值存起来

	//将k的右指针赋值给当前idx的右指针
	//(圈1改为圈6,但此时圈1还在,没有被覆盖掉) 
	r[idx]=r[k];

	//此时k成为了idx的左指针
	//(创建圈4) 
	l[idx]=k;

	//k的右指针指向idx
	
	//k的原右指针为r[k],因此在插入之前
	//l[r[k]]先指向(k+1),再从(k+1)向左指回来,指向k自己
	
	//插入的过程中,r[k]还是指向(k+1),
	//但是在向左指回来时,
	//是指向新插入的idx,
	//(圈1+圈3,这个过程中将圈2覆盖掉,即删掉了) 
	l[r[k]]=idx;
	
	//(覆盖掉圈1相当于删除圈1,并添加圈5)
	r[k]=idx; 
	idx++;  
}

1.4 删除的图解

在这里插入图片描述

1.5 删除代码表示:
//删除 
void remove(int k)
{
	r[l[k]]=r[k];
	l[r[k]]=l[k];
}
1.6 AC代码
#include<iostream>
using namespace std;
const int N=100010;

int m;

//定义
//存值、左指针、右指针、当前指针
int e[N],l[N],r[N],idx;

//初始化
void init()
{
	//1表示右端点.0表示左端点
	r[0]=1,l[1]=0;

	//0和1已经用过了,所以当前指针idx从2开始
	idx=2;
}

//插入
//有两种选择,可以插入某点的左边,
//也可以插入某点的右边

//插入1:在第k点的右边插入一个数x
void add(int k,int x)
{
	e[idx]=x;
	r[idx]=r[k];
	l[idx]=k;
	l[r[k]]=idx;
	r[k]=idx;  
	idx++;
}

//删除 第k个点 
void remove(int k)
{
	r[l[k]]=r[k];
	l[r[k]]=l[k];
}

int main()
{
	//cin,cout先把要输出的东西存入缓冲区,
	//再输出,导致效率降低,
	//而这段语句可以来打消iostream的输入输出缓存,
	//可以节省许多时间,
	//使效率与scanf与printf相差无几
	ios::sync_with_stdio(false);
	
	cin>>m;
	
	init();
	
	while(m--)
	{
		string s;
		cin>>s;
		int k,x;
		
		if(s=="R")//在链表最右端插入数x 
		{
			cin>>x;
			add(l[1],x);
		}
		else if(s=="L")//在链表最左端插入数x 
		{
			cin>>x;
			add(0,x);
		}
		else if(s=="D")//将第k个插入的数删除 
		{
			cin>>k;
			remove(k+1);
		}
		else if(s=="IL")//在第k个插入的数左侧插入一个数 
		{
			cin>>k>>x;
				//在第k个插入的数的左节点后 插入一个数
			add(l[k+1],x);//k+2-1
		}
		else//在第k个插入的数右侧插入一个数
		{
			cin>>k>>x;
			add(k+1,x);//k+2-1
		}
	}
	
	//输出遍历输出时,i=r[i]
	//注意循环的条件是i!=1,不要写成i!=-1,因为1是链表的右边界
	for(int i=r[0];i!=1;i=r[i])
		cout<<e[i]<<' ';
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
双向链表是一种常见的数据结构,与单向链表相比,它每个节点都有两个指针,分别指向前驱节点和后继节点。这样,双向链表可以实现双向遍历,插入和删除操作也更加方便。 以下是用C语言实现双向链表的代码: ```c #include <stdio.h> #include <stdlib.h> // 双向链表节点结构体 typedef struct ListNode { int val; struct ListNode *prev; struct ListNode *next; } ListNode; // 创建双向链表节点 ListNode *createNode(int val) { ListNode *node = (ListNode *)malloc(sizeof(ListNode)); node->val = val; node->prev = NULL; node->next = NULL; return node; } // 插入节点到双向链表头部 ListNode *insertAtHead(ListNode *head, int val) { ListNode *node = createNode(val); if (head == NULL) { head = node; } else { node->next = head; head->prev = node; head = node; } return head; } // 插入节点到双向链表尾部 ListNode *insertAtTail(ListNode *head, int val) { ListNode *node = createNode(val); if (head == NULL) { head = node; } else { ListNode *cur = head; while (cur->next != NULL) { cur = cur->next; } cur->next = node; node->prev = cur; } return head; } // 删除双向链表中的节点 ListNode *deleteNode(ListNode *head, int val) { if (head == NULL) { return NULL; } ListNode *cur = head; while (cur != NULL && cur->val != val) { cur = cur->next; } if (cur == NULL) { return head; } if (cur == head) { head = head->next; if (head != NULL) { head->prev = NULL; } } else { cur->prev->next = cur->next; if (cur->next != NULL) { cur->next->prev = cur->prev; } } free(cur); return head; } // 打印双向链表 void printList(ListNode *head) { while (head != NULL) { printf("%d ", head->val); head = head->next; } printf("\n"); } // 主函数 int main() { ListNode *head = NULL; head = insertAtHead(head, 1); head = insertAtHead(head, 2); head = insertAtTail(head, 3); printList(head); // 2 1 3 head = deleteNode(head, 2); printList(head); // 1 3 head = deleteNode(head, 3); printList(head); // 1 head = deleteNode(head, 1); printList(head); // return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值