首页 > 编程知识 正文

栈和队列都是什么结构,栈和队列的概念

时间:2023-05-04 12:56:05 阅读:160355 作者:644

堆栈和队列1,堆栈和队列的定义,区别,存在的意义1 .堆栈的定义(1)堆栈:堆栈实际上是线形表,只有在固定的段中才能插入或删除要素,在进行数据插入或删除的段中被称为堆栈顶部其原则是后进先出。

(2)栈的核心操作:取三大核心操作,栈、出栈、栈顶要素

)3)堆栈形象理解:子弹夹你看过吧。 子弹在被按入时相当于一个个要素,夹子相当于堆栈。 先压入的子弹最后被压出,先压入的元素最后出来,也就是后退先出来。

2 .队列定义(1)队列:首先,队列也是一个特殊的线性表,它可以在一端插入数据,在另一端删除数据。 队伍中有队头、队尾、队头的要素。 其原则是先入为主。

)队列的核心操作)三个核心操作分别是队列、出队列、队列的首元素。

)3)关于矩阵的形象)列车穿越隧道时,列车的车头相当于矩阵的车头,列车的尾部相当于矩阵的尾部。 列车穿越隧道时,头先进隧道,头也先出隧道,尾先进后出隧道。 排队是指先进入的元素先排队,后进入的元素后排队。

3 .堆栈和队列的不同(1)堆栈和队列的进入方式的不同)堆栈是后进先出,队列是先进先出。

)2)堆栈和队列在具体安装时操作的位置不同)堆栈是后进先出的,所以在一级操作。 队列是先进先出的,实现时在两端进行。 在Java标准库中实现队列时,将根据链表来实现。

4 .堆栈和队列存在的含义如上所述,堆栈和队列是典型的线性表,都是基于线性表(顺序表和链表)实现的。 那么,研究堆栈和队列的目的是什么? 因为在定义了堆栈和队列之后,只有那三个操作。 那三种操作是最常用的,支持的操作越少,使用时关注点也越少,使用起来越方便。 在计算机中“多为少”,少则意味着功能少,死板。 也就是说有很多功能,使用的时候操作的心越多,就越容易出错。 综上所述,堆栈和队列存在的意义是减少线性列表的基本操作,提取常用操作,使人们更容易使用,更不易出错。

二、堆栈的实现1 .基于顺序表实现堆栈的操作是在一端进行的,所以选择在顺序表的末尾进行操作。 也就是说,堆栈用末尾的插件实现,外部堆栈用末尾的删除实现,取堆栈的开头要素是末尾要素。

注意:在用顺序表实现堆栈时选择在顺序表的末尾进行,但并不是不能在顺序表的开头实现。 只是,在实现头部的时候,无论是插头还是削头都必须进行要素的搬运,因为时间的复杂性太高,所以不选择。

以下是根据顺序表实现的堆栈。

publicclassmystackforarraylist (//具有使用顺序表实现堆栈//堆栈的特征。 为了后进先出,在顺序表中,在末尾插入堆栈,在末尾删除堆栈,取堆栈的开头要素,使用[]操作//制作数组来表现顺序表,堆栈的容量为100,如果不够的话,可以在后面扩展privivator //一、栈的实现:顺序表的实现//1 .进入栈是顺序表中的尾插,也可以通过头插来实现,但对于搬运效率太低,需要考虑publicvoidpush(intval )//特殊情况size; //堆栈要堆栈到size//2.需要返回值,它可以在Integer中接收,并返回null。 public Integer pop ()//特殊情况if ) size==0) ) { return null; //一般为int ret=data[size-1]; //保存该堆栈的元素,然后返回到size--; //要退出堆栈,请单击size-- return ret; //3 .堆栈顶部元素public Integer peek () ) /特殊情况if(size==0) ) { return null; } return data[size - 1]; }2.基于链表实现堆栈采用链表实现堆栈:采用链表实现堆栈时,我们操作的段落选择开头。 用插入头表示堆栈,用删除头表示堆栈,取堆栈的最上位要素就是取得链表的head的值。

注意:选择并实现在链表的开头,不是在链表的末尾不能实现,而是在末尾进行操作时,由于每个tail都会更新,所以用一个引用记录tail的位置是,metail

以下是基于链表实现的堆栈。

class Node { int val; 节点下一个; 公共节点(intval ) { this.v

al = val; }}// 链表实现栈,头插表示入栈,头删表示出栈,取栈顶元素。链表头插,头删还是为了减少内存的开销public class MyStackForLinkedList { // 先搞一个链表 private Node head = null; // 1.入栈,头插,不需要返回要插入的值 public void push(int val) { // 将要插入的元素放在链表里边 Node newNode = new Node(val); // 特殊情况的处理,空链表 if (head == null) {// 链表本来是空的 head = newNode; return; } // 处理一般情况 newNode.next = head; head = head.next; } // 2.出栈,就是头删,出栈要返回一个值 public Integer pop() {// 用Integer来为了可以返回那个null // 特殊情况处理,链表是空 if (head == null) { return null; } // 链表之中只有一个元素,删除就没有元素了 if (head.next == null) { int ret = head.val; head = null; return ret; } // 一般情况的处理 int ret = head.val; head = head.next; return ret; } // 3.取栈顶元素 public Integer peek() { // 特殊情况:要是链表是空的,没得取,返回null if (head == null) { return null; } return head.val; }} 三、队列的实现 1.基于链表来实现队列

队列的操作在两端进行,所以我们选择在链表的尾部进行插入表示入队列,头删来表示出队列,用 head.val 操作来表示取队首元素。
注意:这里的头删和尾插的顺序是可以进行交换的,头和尾只是选的两个引用罢了。咋样选取都是一样的。

下边是基于链表来实现的队列:

// 基于链表来实现队列// 因为队列是先进先出的,所以用尾插表示入队列。头删表示出队列,.操作表示取队列元素public class MyQueueForLinkedList { // 弄一个Node内部类,要带上static,为了和外部的实例无关 static class Node { int val; Node next; public Node(int val) { this.val = val; } } // 先创建一个链表,并记录其头节点和尾节点,方便后边的进行尾插 Node newHead = null; Node newTail = null; // 1.入队列,就是尾插,为了和Java库中的队列保持一致,用boolean返回值 public boolean offer(int val) { // 将要插入的值放在Node 节点里面 Node newNode = new Node(val); // 情况特殊的处理 if (newHead == null) { // 头节点和尾节点都是要插入的值 newHead = newNode; newTail = newNode; return true; } // 一般情况的处理 newTail.next = newNode; newTail = newTail.next; return true; } // 2.出队列,就是头删,注意头删也是要返回那个要删除的值 public Integer poll() { // 特殊情况的处理,链表为空没得删 if (newHead == null) { return null; } // 链表只要一个元素 if (newHead.next == null) { int ret = newHead.val; // 新头节点就没有了,就是null newHead = null; return ret; } // 处理一般情况的处理 int ret = newHead.val; newHead = newHead.next; return ret; } // 3.取队列首元素 public Integer peek() { // 特殊情况的处理 // 链表为空,没得取 if (newHead == null) { return null; } // 一般情况的处理 return newHead.val; }} 2.基于顺序表实现队列

(1)基本思想:创建两个引用head和tail表示队列的头部和尾部,开始的时候head和tail都表示null,此时head == tail表示的是队列是空的 。
(2)出现的问题:每入一次队列给tail进行++,要是tail已经满了的时候就让tail == head,此时head和tail也是相等的,所以就不能区别队列到底是空的还是满的。
(3)解决方法:
方法1:是空上让出一个内存空间,不让tail和head重合。这种方法浪费了一块内存空间,直接让那个空间是空的,也就是用这种方法后:head == tail表示空, tail == head - 1表示队列是满的。看起来非常不好看。
方法2:创建一个变量size,时刻记录队列里边元素的多少,没进行一次入队操作进行size++,每进行一次出队操作让size–,最后用size的值来区别队列是空的还是满的。

下边是基于顺序表实现的队列:

public class MyQueueForArrayList { // 用顺序表来实现队列 // 基本思路:让head = 0,tail = 0;队列的长度是[head,tail),包含head不包含tail。 // 入队:tail++,入完判断tail的值,要是 == data.length,让tail从0又开始 // 出队列:让head++ // 这样操作当head == tail时,有两种结果:1,是队列是空的时候 2,是队列是满的时候 // 所以用size来记录一下顺序表的具体的大小,根据size来判断队列是否为满。 // 创建数组 public int[] data = new int[100]; public int head = 0; private int tail = 0; // 这个用来判断队列到底是空的还是满的 private int size = 0; // 1.入队操作,tail++,然后判断size的值 public boolean offer(int val) { // 特殊情况的处理,先判断size的值的大小,每一次都是以size来判断队列是否是空的 if (size == data.length) {// 队列已经满了 return false; } // 一般情况的处理 data[tail] = val; // 完成插入之后,判断一下tail的值的 if (tail == data.length) {// 要是让tail从0开始 tail = 0; } // 否则更新size的值 size++; return true; } // 2.出队列,核心操作,头删,head-- public Integer poll() { // 特殊情况的处理 // 队列为空,没得取 if (size == 0) { return null; } // 一般情况的处理 int ret = data[head]; head++; // 每一次要判断head的值是否到达了末尾 // 要是到达了末尾,让head也是0 if (head == data.length) { head = 0; } size--; return ret; } // 3.取队首元素 public Integer peek() { // 特殊情况的处理 if (size == 0) {// 为空,没得取 return null; } return data[head]; }}

好了以上就是我学完栈和队列所了解到的内容,希望对大家有所帮助,要是有错误的地方还望大家海涵并指出。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。