数据结构基础

链表

为什么要用链表

​ 数组作为一个顺序储存方式的数据结构,可是有大作为的,它的灵活使用为我们的程序设计带来了大量的便利;但是,数组最大的缺点就是我们的插入和删除时需要移动大量的元素,所以呢,大量的消耗时间,以及冗余度难以接收。

​ 链表可以灵活地去解决这个问题,插入删除操作只需要修改指向的对象就可以了,不需要进行大量的数据移动操作。

单链表
初始化
static class Node{//定义结点类
    int value;//本身的值
    Node next;//指向下一个结点
    public Node(int value, Node next) {
        this.value = value;
        this.next = next;
    }
}
Node head = new Node(-1,null);//头结点
Node end = new Node(-1, null);//尾结点
Node per = head;
for(int i=1;i<=10;i++) {
    per.next = new Node(i, null);
    per = per.next;
}
per.next = end;
插入

​ 插入前:

图片描述

​ 插入后:

图片描述
Node now;//待插入结点
now.next = head.next;//此节点的next为插入位置上一个结点的下一个结点
head.next = now;//此节点位置的上一个结点的下一个结点为now
删除

​ 删除前:

图片描述

​ 删除后:

图片描述
Node now;//待删除结点
head.next = now.next;
双链表
初始化
static class N{
    N last;
    int value;
    N next;
    public N(N last, int value, N next) {
        this.last = last;
        this.value = value;
        this.next = next;
    }
}
Node first = new Node(null,-1,null);//头结点
Node end = new Node(null,-1, null);//尾节点
Node per = first;
for(int i=1;i<=10;i++) {
    per.next = new N(per,i, null);
    per = per.next;
}
end.last = per;
per.next = end;
插入

​ 插入前:

图片描述

​ 插入后:

图片描述
Node now;//待插入结点
now.next = first.next;
first.next.last = now;
first.next = now;
now.last = first;
删除

​ 删除前:

图片描述

​ 删除后:

图片描述
Node now;//待删除结点
now.last.next = now.next;
now.next.last = now.last;
例题:左移右移(双链表解法)

题目链接:左移右移 - 蓝桥云课 (lanqiao.cn)

图片描述

​ 思路:

​ 1.创建双链表并完成初始化,初始元素为 1 1 1 ~ n n n

​ 2.无论 x x x 左移或右移,都要先将 x x x 从原位置删除,为了便于获取 x x x 对应的 N o d e Node Node 结点,用 M a p Map Map 存储 x x x v a l u e value value x x x 的结点;

​ 3.如果 x x x 为左移,就将 x x x 对应的 N o d e Node Node 结点插入到头结点后;

​ 4.如果 x x x 为右移,就将 x x x 对应的 N o d e Node Node 结点插入到尾节点前;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

public class 左移右移_双链表 {
	static class Node{
		Node up;
		int value;
		Node down;
		public Node(Node up, int value, Node down) {
			this.up = up;
			this.value = value;
			this.down = down;
		}
	}
	public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        String[] s = in.readLine().split(" ");
        int n = Integer.parseInt(s[0]);
        int m = Integer.parseInt(s[1]);
        Map<Integer, Node> map = new HashMap<>();
        Node first = new Node(null, -1, null);
        Node last = new Node(null, -1, null);
        Node no = first;
        for(int i=1;i<=n;i++) {
        	no.down = new Node(no, i, null);
        	no = no.down;
        	map.put(i, no);
        }
        last.up = no;
        no.down = last;
        for(int i=0;i<m;i++) {
        	s = in.readLine().split(" ");
        	char ch = s[0].charAt(0);
        	int x = Integer.parseInt(s[1]);
        	Node node = map.get(x);
        	node.up.down = node.down;
        	node.down.up = node.up;
        	if(ch=='L') {
        		node.down = first.down;
        		first.down.up = node;
        		first.down = node;
        		node.up = first;
        	}else {
        		node.up = last.up;
        		last.up.down = node;
        		node.down = last;
        		last.up = node;
        	}
        }
        no = first.down;
        while(no!=last) {
        	System.out.print(no.value+" ");
        	no = no.down; 
        }
	}
}

​ 栈( S t a c k Stack Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。

​ 栈顶( T o p Top Top):线性表允许进行插入删除的那一端。

​ 栈底( B o t t o m Bottom Bottom):固定的,不允许进行插入和删除的另一端。

img
常用方法
Stack<Integer> stack = new Stack();
boolean is = stack.isEmpty();//判断此栈是否为空
int n = stack.peek();//获取栈顶的元素,但不删除
int m = stacl.pop();//获取并删除栈顶的元素
stack.push(10);//将10压入栈中
stack.clear();//清空栈
判断括号序列是否合法
public static boolean check(String s){
    Stack<Character> stack = new Stack();
    char[] ch = s.toCharArray();
    for(int i=0;i<ch.length;i++){
        if(ch[i]=='(')
            stack.push(ch[i]);
        else if(stack.isEmpty())
            return false;
        else
            stack.pop();
    }
    return stack.isEmpty();
}

队列

队列

​ 队列( q u e u e queue queue)是一种先进先出的、操作受限的线性表。

图片描述

​ 队列这种数据结构非常容易理解,就像我们平时去超市买东西,在收银台结账的时候需要排队,先去排队的就先结账出去,排在后面的就后结账,有其他人再要过来结账,必须排在队尾不能在队中间插队。

常用方法
Queue<Integer> queue = new LinkedList<>();
queue.peek();//获取队头元素,但不删除
queue.poll();//获取并删除队头元素
queue.clear();//清空队列
queue.push(11);//将11存放到队列中
例题:左移右移(栈 + 队列解法)

题目链接:左移右移 - 蓝桥云课 (lanqiao.cn)

图片描述

​ 思路:

​ 1.如果一个数先移动到最左边,再移动到最右边,那么最后输出的时候这个数一定是在最右边,也就是一个数最终出现在哪里,以他最后一次出现为准;

​ 2.为了避免一个数重复判断,而且要以他最后一次出现时的 L L L R R R 操作为最终操作,所以可以先将全部输入分别存放到 c h a r char char 类型数组和 i n t int int 类型数组中,然后逆序判断,并且用一个数组来表示这个 x x x 有没有出现过;

​ 3.因为要对输入做逆序操作,所以,逆序时最后出现的 L L L 对应的 x x x 在输出的最前面,然后之后出现的 L L L 对应的 x x x 依次输出,即先入先出,可以用队列来存储进行 L L L 操作的 x x x

​ 4.逆序时最后出现的 R R R 对应的 x x x 在输出的最后面,然后之后出现的 R R R 对应的 x x x 依次在前,即后入先出,可以用栈来存储进行 R R R 操作的 x x x

​ 5.输出时,先输出队列中的元素,然后将 1 1 1 ~ n n n 中没有出现过的值按序输出,最后输出栈中的元素;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class 左移右移_栈_队列 {

	public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        String[] s = in.readLine().split(" ");
        int n = Integer.parseInt(s[0]);
        int m = Integer.parseInt(s[1]);
        int[] a = new int[n+1];
        char[] c = new char[m];
        int[] x = new int[m];
        for(int i=0;i<m;i++) {
        	s = in.readLine().split(" ");
            c[i] = s[0].charAt(0);
            x[i] = Integer.parseInt(s[1]);
        }
        Stack<Integer> r = new Stack<>();
        Queue<Integer> l = new LinkedList<>();
        for(int i=m-1;i>=0;i--) {
        	if(a[x[i]]==0) {//判断x[i]是否出现过
        		a[x[i]] = 1;//若x[i]没有出现过
        		if(c[i]=='L')
        			l.add(x[i]);
        		else
        			r.push(x[i]);
        	}
        }
        while(l.size()!=0) //输出队列中元素
        	System.out.print(l.poll()+" ");
        for(int i=1;i<=n;i++) 
        	if(a[i]==0) //a[i]为0,表示i没有出现过
        		System.out.print(i+" ");
        while(r.size()!=0) //输出栈中元素
        	System.out.print(r.pop()+" ");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值