基础数据结构-链表,栈,队列

本文介绍了链表(单链表和双链表)的结构、操作方法,如尾部插入、中间插入和删除,以及如何使用双链表解决特定问题。此外,还讨论了栈和队列的基本概念,包括栈的顶部操作、队列的头部和尾部操作,以及它们在实际编程中的应用。
摘要由CSDN通过智能技术生成

链表

常见的链表有单链表和双链表

单链表:每个结点有一个next指针指向下一个结点,data存放数据

双链表:每个结点有一个next指针指向下一个结点,prev指针指向上一个结点,data存放数据。

4的下一结点为-1,表示下一结点为空,不存在下一结点

p是指向上一结点,e是指向下一结点

单链表

实现单链表只需要两个数组int e[N]和int data [N],还需要tail和head来表示尾结点和头节点(头节点一般不存放数据),idx表示当前已用的内存空间,用于开店,我们用-1表示空。

e[i]表示地址为i的结点上的下一个结点的地址(即数组下标)。

data[i]表示地址为i的结点上的数据。

尾部插入结点    插入一个节点到尾部:e[tail]=++idx(++idx先把值给赋出来),e[idx]=-1(将新的伪结点设为空,表示后面没有结点),data[idx]=val(地址的值赋进来),tail=idx(伪结点变成这个新的结点);

中间插入结点    往地址adr的后面插入一个结点,e[++idx]=e[adr](插入结点的下一个指针指向)比如要在3,4中间插一个5,3指向4,让5也指向4,e[adr]=idx(比如让3指向5),data[idx]=val(赋值);

删除   将adr后面的结点删除(adr部位tail):e[adr]=e[e[adr]];(当前这个位置的指针指向下下个指针就可以了)

单链表只能处理”后面“的操作,不能找到前一个点。

双链表

单链表和双链表的区别在于,双链表不仅在next指针(e数组)来表示下一个结点,还有一个prev指针(p数组)来表示上一个结点的位置。

例题

给定按从小到大的顺序排列的数字1到n,随后对他们进行m次操作,每次将一个数字x移动到数字y之前或之后,请输出完成这m次操作后他们的顺序

输入格式

第一行为两个数字n,m表示初始状态为1到n的从小到大排序,后续有m次操作。

第二行到第m+1行,每行三个数x,y,z,当z=0是,将x移动到y之后,当z=1时,将x移动到y之前。

输出格式

一行,n个数字,中间用空格隔开,表示m次操作完成后的排列顺序。

样例输入

5 3

3 1 0

5 2 1

2 1 1

样例输出

2 1 3 5 4

思路

利用双链表去模拟

列表写成循环列表

package shuanlianbiao;
import java.util.*;
public class chapter1 {
	public static int[]pre=new int [(int)1e4+1];
	public static int[]next=new int [(int)1e4+1];
	public static void res(int x) {
		int a=pre[x];
		int b=next[x];
		next[a]=b;
		pre[b]=a;
	}//删除
	public static void add(int x,int y) {
		int z=next[y];
		pre[z]=x;
		pre[x]=y;
		next[y]=x;
		next[x]=z;
	}
	public static void main(String agrs[]) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int m=scan.nextInt();
		for(int i=1;i<n;i++) {
			pre[i]=i-1;
			next[i]=i+1;
		}
		next[0]=1;
		pre[0]=0;
		next[n]=0;
		pre[n]=n-1;
		for(int i=0;i<m;i++) {
			int x=scan.nextInt();
			int y=scan.nextInt();
			int z=scan.nextInt();
			if(z==0) {
				y=pre[y];
			}
			res(x);
			add(x,y);
		}
		for(int i=next[0];i>0;i=next[i]) {
			System.out.print(i+" ");
		}
	}
}

栈可以看作只能对顶部操作的数组,结构比较简单,只需要一个数组表示内存空间,一个数字表示栈顶即可

int stk[N],top;

往栈内新增元素:stk[++top]=x;(顶部操作)

删除栈顶元素:top--

判断栈是否为空:top==0

 例题

小蓝有一个长度为 n 的括号串,括号串仅由字符 ( 、 ) 构成,请你帮他判断一下该括号串是否合法,合法请输出 Yes ,反之输出 No 。

合法括号序列:

  1. 空串是合法括号序列。

  2. 若 s 是合法括号序列,则 ( s ) 也是合法括号序列。

  3. 若 s,t 都是合法括号序列,则 st 也是合法括号序列。

例如 ()() , (()) , (())() 均为合法括号序列。

输入格式

第一行包含一个正整数 n ,表示括号串的长度。

第二行包含一个长度为 n 的括号串。

输出格式

输出共 11 行,若括号串合法请输出 Yes ,反之输出 No 

 代码

package zhan;
import java.util.*;
public class chapter1 {
	public static void main(String args[]) {
		Scanner scan=new Scanner(System.in);
		char[] c=scan.next().toCharArray();
		int top=0;
		boolean f=true;
		for(char x:c) {
			if(x=='(') {
				top++;
			}else {
				top--;
				if(top<0) {
					f=false;
				}
			}
			                                                   
			
		}
		if(top!=0) {
			f=false;
		}
		if(f) {
			System.out.print("YES");
		}else {
			System.out.print("No");
		}
	}
}

队列

队列是一个可以对头和尾操作的数组

需要一个数组,两个整形变量一个表示头head一个表示尾tail

int q[N],h=1,t=0;

有效元素的区间为[h,t]

入队:q[++t]=x;

出队:h++;

检查队列是否为空:t-h+1==0

例题

小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。

这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。

假设内存中有 M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过 M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入 M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。

假设一篇英语文章的长度为 N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

输入描述

输入共 2 行。每行中两个数之间用一个空格隔开。

第一行为两个正整数 M 和 N,代表内存容量和文章的长度。

第二行为 N 个非负整数,按照文章的顺序,每个数(大小不超过 1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。

其中,0<M≤100,0<N≤1000。

输出描述

输出共 1 行,包含一个整数,为软件需要查词典的次数。

输入输出样例

示例 1

输入

3 7
1 2 1 5 4 4 1

输出

5

示例2 

输入

2 10
8 824 11 78 11 78 11 78 8 264 

输出

6

 

package duilie;
import java.util.*;
public class chapter1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan=new Scanner(System.in);
		int m=scan.nextInt();
		int n=scan.nextInt();
		int queue[]=new int[n+1];
		int h=1,t=0,res=0;
		for(int i=0;i<n;i++){
			int x=scan.nextInt();
			boolean f=true;
			for(int j=h;j<=t;j++) {
				if(queue[j]==x) {
					f=false;
				}
			}
			if(f) {
				queue[++t]=x;
				res++;
			}
			if(t-h+1>m) {
				++h;
			}
		}
		System.out.println(res);
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值