数据结构java实现———栈、队列的实现及应用

数据结构java实现——栈的顺序存储+共享结构+链式存储

栈是指只在表尾进行插入和删除的线性表,后进先出(List In First Out)

栈的基本操作

栈在java中的定义,栈的入栈 出栈 检验空满栈 栈的动态扩容 降容 输出等操作

栈结构

栈结构体的结构部分,在java直接写在一个类里面。

Object[] elements;
    int top=-1;//始终指向栈顶
    int lengthStack;
package com.javase.datastruct.stack;

import com.sun.javaws.IconUtil;

import java.util.Arrays;

public class Stack {
    public static void main(String[] args) {
        /*栈的基本测试*/
        MyStack s=new MyStack(5);
        System.out.println("栈的初始状态"+s);
        if(s.isEmpty()){
            //入栈
            System.out.println("操作1:入满栈");
            for(int i=s.top+1;i<s.lengthStack;i++) {
                s.push(i);
            }
            System.out.println("——————————————————————————————");
            System.out.println("检验栈是否为满:"+s.isFull());
            System.out.println("操作2:出栈");
            for(int i=s.top;i>=0;i--) {
                s.pop();
            }
        }
        System.out.println("检验栈是否为空:"+s.isEmpty());
        System.out.println("——————————————————————————————");
        //存放类
        System.out.println("操作3:数组中放入类");
        Student student=new Student("张三",22);
        s.push(student);
        System.out.println("显示所有的栈元素");
        System.out.println(s);
        s.pop();//单独出类
        System.out.println(s);
        /*数组的扩容*/
        //之前用C++编写的时候 知道动态结构
        //昨天有瞄到数组的合并,想了一下 或许可以用到  试试  发现不行 因为数组大小在栈这个类创建的时候就定义了
        //MyStack s2=new MyStack(3);
        /*if(s.isEmpty()){
            for(int i=s.top+1;i<s.lengthStack;i++) {
                s.push(i);
            }
        }
        if(s.isFull()){
            System.arraycopy(s.elements,s.top,s2,s2.lengthStack);
        }*/
        //只能用动态结构
        if(s.isEmpty()){
            for(int i=s.top+1;i<s.lengthStack;i++) {
                s.push(i);
            }
        }
        if(s.isFull()){
            System.out.println("——————————————————————————————");
            System.out.println("操作4:扩容");
            s.addSize(2);
            for(int i=s.top+1;i<s.lengthStack;i++){
                s.push(i);
            }
          /*  for(int i=s.top;i>=0;i--) {
                s.pop();
            }*/
            System.out.println("——————————————————————————————");
            System.out.println("操作5:降容,并显示出被挤出的元素");
            System.out.println(s);
            s.subSize(2);
            System.out.println("检验,降容后的栈");
            System.out.println(s);
        }
    }
}

//静态栈的实现
//先进后出
class MyStack{
    /*构造基本结构*/
    Object[] elements;
    int top=-1;//始终指向栈顶
    int lengthStack;

    //构造一个构造方法  实现调用的时候,确定栈的长度
    public MyStack(int lengthStack) {
        this.lengthStack = lengthStack;
        elements= new Object[lengthStack];//同时为栈内的数组产生一个具体内存空间的对象
    }
    //判断是否已经满
    public boolean isFull(){
        return top==this.lengthStack-1;
    }

    public boolean isEmpty(){
        return top==-1;
    }
    //压栈
    public void push(Object obj){
        if(!isFull())//如果未满
            elements[top+1]=obj;
        else{
            System.out.println("栈满");
            return;
        }
        top++;
    }

    //出栈
    public Object pop(){
        if(isEmpty()){
            System.out.println("空栈,无需弹出");
            return 0;
        }
        Object obj1=elements[top];
        System.out.println("出栈:"+obj1);
        elements[top]=null;
        top--;
        return obj1;
    }

   @Override
    public String toString() {
        return "MyStack{" +
                "elements=" + Arrays.toString(elements) +
                '}';
    }

    //增加一个栈的动态扩容
    public void addSize(int loadFactor){
        lengthStack=(int)(lengthStack*loadFactor);
        //Object[] elements=(Object[]) new Object(lengthStack);
        this.elements=Arrays.copyOf(elements,lengthStack);
    }

    //降容 降低两个
    public void subSize(int subFactor){
        if(this.lengthStack-subFactor>=0){
            for(int i=top;i>(this.lengthStack-1-subFactor);i--){
                this.pop();
            }
            this.lengthStack=this.lengthStack-subFactor;
            this.elements=Arrays.copyOf(elements,this.lengthStack);
        }
    }


}
//在数组中存放一个类
class Student{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在这里插入图片描述
——————
之前在cpp里会用头文件申明一下方法
java就可以用到前些天学的接口

package com.javase.datastruct.stack;

public interface StackMethod {
    //接口包含常量 和 未实现的抽象方法
    boolean isFull();
    boolean isEmpty();
    void push(Object obj);
    Object pop();
    void addSize(int loadFactor);
    void subSize(int subFactor);

}

class MyStack implements StackMethod

注:复习的java自带函数不用在接口中写出来

栈自动扩容函数

public void addSize(int loadFactor){
        lengthStack=(int)(lengthStack*loadFactor);
        //Object[] elements=(Object[]) new Object(lengthStack);
        this.elements=Arrays.copyOf(elements,lengthStack);
    }

数组扩容还可以用System.arraycopy();库函数

栈降容函数

 public void subSize(int subFactor){
        if(this.lengthStack-subFactor>=0){
            for(int i=top;i>(this.lengthStack-1-subFactor);i--){
                this.pop();
            }
            this.lengthStack=this.lengthStack-subFactor;
            this.elements=Arrays.copyOf(elements,this.lengthStack);
        }
    }

两个栈的共享空间

这一篇写的很详细了
java实现

package com.javase.datastruct.stack;

import java.util.Arrays;
import java.util.Scanner;

public class StackShared {
    public static void main(String[] args) {
        MyStack1 s2=new MyStack1(5);
        System.out.println("栈的初始状态"+s2);
        if(s2.isEmpty()){
            //入栈
            System.out.println("操作1:入栈,“左起入栈输入1,右起入栈输入2”"+'\n'+"请选择:");
            Scanner scanner = new Scanner(System.in);
            int stnum=scanner.nextInt();
            System.out.println("stnum:"+stnum);
            while(stnum!=1&&stnum!=2){
                System.out.println("输入错了,请重新输入!");
                stnum=scanner.nextInt();
            }
            if(stnum==1){//左输入
                for(int i=0;i<(s2.lengthStackShare+1)/2;i++){
                    s2.push(i,stnum);
                }

                for(int i=0;i<(s2.lengthStackShare+1)/2;i++){
                    System.out.println(s2.pop(i,stnum));
                }
            }else{
                for(int j=s2.lengthStackShare;j>=s2.lengthStackShare/2;j--){
                    s2.push(j,stnum);
                }
                for(int j=s2.lengthStackShare;j>=s2.lengthStackShare/2;j--){
                    System.out.println(s2.pop(j,stnum));
                }
            }
        }
    }
}


class MyStack1 implements StackSharedMethod{
    Object[] elements;
    private int top1=-1;
    private int top2;
    int lengthStackShare;

    public MyStack1(int lengthStackShare) {
        this.lengthStackShare = lengthStackShare;
        elements=new Object[this.lengthStackShare];
        top2=this.lengthStackShare;
    }

    public boolean isFull(){
        /*if(top1+1==top2||top1==this.lengthStackShare-1||top2==0)
            return true;*/
        return top1+1==top2;//上面括号处意思等同于这步
    }
    public boolean isEmpty(){
        return top1==-1&&top2==this.lengthStackShare;//只有两个顶点指针 都在最顶端 才是为空栈
    }
    public int push(Object obj,int stacknumber){//对于两端进元素,需要一个判别式对其进行判断
        if(this.isFull())
            return 0;
        else{
            if(stacknumber==1){
                top1++;
                this.elements[top1]=obj;
            }
            if(stacknumber==2){
                top2--;
                this.elements[top2]=obj;
            }
        }
        return 1;
    }
    public Object pop(Object obj,int stacknumber){
        Object value = null;
        if(this.isEmpty())
            return 0;
        if(stacknumber==1){
            value=this.elements[top1];
            this.elements[top1]=null;
            top1--;
        }
        if(stacknumber==2){
            value=this.elements[top2];
            this.elements[top2]=null;
            top2++;
        }

        return value;
    }

    @Override
    public String toString() {
        return "MyStack1{" +
                "elements=" + Arrays.toString(elements) +
                '}';
    }
}

栈结构:

Object[] elements;
    private int top1=-1;
    private int top2;
    int lengthStackShare;

写在一个里面,同时它的实现方法可以写在同一个类里,也可以使用继承实现。

栈的链式存储结构java实现

链式结构的结构

class Node{
    Object data;//元素
    Node next;//相当于指针  指向下一个
    public Node(){

    }

    public Node(Object data) {
        this.data = data;
        //this.next = next;
    }
}

链式结构的实现部分
Node top; 是一直指向顶点的一个指针
size用来记录栈的节点个数,可灵活使用

class stackLNode implements StackLink{
    Node top;//存放栈顶点结点
    private int size;//栈元素个数  每次创建一个栈  其内存都可以不一样 所以需要设置

    public stackLNode(){//创建一个空栈
        InitStack();
    }
    private void InitStack(){
        top=null;
        this.size=0;
    }
    public stackLNode(Node t, int size) {//指定一个栈  t应该是一个新建的结点
        this.top = t;
        this.size = size;
    }

    public boolean isEmpty(){
        return this.size==0;
    }

    public void push(Object data){
        Node node=new Node(data);//建立一个新的栈结点  并赋予元素
        node.next=top;//将原顶点的空信息 赋予新结点的next
        top=node;// 然后又使得新建立的结点为top    top是存放栈顶点的结点  最新的一个就是栈顶
        size++;
        System.out.println(data+"压栈成功");
    }
    public Object pop(){
        //出栈 栈的出栈原则  出栈顶那个元素
        Object value;
        if(isEmpty()){
            System.out.println("空栈");
            return 0;
        }
        value = top.data;//因为top是指向栈顶的指针
        Node Oldtop=top;
        top=top.next;
        Oldtop=null;
        size--;
        return value;
    }

    @Override
    public String toString() {
        return "stackLNode{" +
                "top=" + top +
                '}';
    }
}

数据结构java实现——队列的顺序存储、链式结构

顺序存储结构

队列遵循一个先进先出的原则
而栈遵循先进后出,所以栈有压栈 弹栈的原则 都是离栈顶最远的结点元素

误区:1**********当 队列不为空时 头指针永远指向第一个位置---------》》》实际上头指针如果永远在第一个的话,那么后面出队,就要每次都移动了,
所以解决方法是头指针始终在第一个元素那,所以对应只有当头指针和尾指针相等时 即为空队列

//队列的顺序存储结构+链式结构

//队列遵循一个先进先出的原则
//而栈遵循先进后出,所以栈有压栈  弹栈的原则  都是离栈顶最远的结点元素

import java.util.Arrays;
import java.util.Scanner;

/*误区:1**********当 队列不为空时  头指针永远指向第一个位置---------》》》实际上头指针如果永远在第一个的话,那么后面出队,就要每次都移动了,
所以解决方法是头指针始终在第一个元素那,所以对应只有当头指针和尾指针相等时  即为空队列
* 误区:2**********
* */
public class queueNode implements queueNodeinterface {
    Object[] obj;
    int head=0;
    int tail=0;//当队列不为空时 尾指针永远指向最后一个元素的下一个位置
    int lengthqueue;

    public queueNode(int lengthQueue) {
        this.lengthqueue = lengthQueue;
        obj=new Object[this.lengthqueue];
    }

   public boolean isFull(){
        return this.tail==this.lengthqueue;
   }
    public boolean isEmpty(){
        return this.head==this.tail;
    }
    public int EnQueue(){
        if(isEmpty()){
            System.out.println("空队列,请输入元素入队:");
            //空队列的话,为了节约空间,将头指针和尾指针重置
            this.head=this.tail=0;
            Scanner scanner=new Scanner(System.in);
            //StringBuffer s=scanner.nextLine();//遇到一个问题  那就是StringBuffer如何和Scanner结合
            //StringBuffer s=new StringBuffer("a");
            String s=scanner.nextLine();
            obj[this.head]=s;
            ++this.tail;
            return 0;
        }
        if(!isFull()){
            System.out.println("队列未满,请输入元素入队");//入队列时  从队尾入  然后队尾指针往后指一个   ***保证每次入队结束之后队尾所指向的都是为空结点
            Scanner scanner=new Scanner(System.in);
            String s=scanner.nextLine();
            obj[this.tail]=s;
            ++this.tail;
            return 0;
        }
        else{
            /*对列 即不为空 又满了,进行扩队列处理*/
            //*********************************************************扩队列处理
            System.out.println("队列满,请选择操作:1:出队,2:队列扩容,3:跳出循环");
            Scanner scanner=new Scanner(System.in);
            int select=scanner.nextInt();
            while(select!=1&&select!=2&&select!=3){
                System.out.println("输入有错,请重新输入!");
                select=scanner.nextInt();
            }
            if(select==3){
                return 0;
            }
            if(select==1){
                System.out.println("出队----》请选择出队人数!");
                int dequeuenum=scanner.nextInt();
                while(dequeuenum>0){
                    DeQueue();
                    --dequeuenum;
                }
            }else{
                System.out.println("队列动态扩容:请选择扩容的容量!");
                int expansion=scanner.nextInt();
                this.lengthqueue=(int)(this.lengthqueue*expansion);
                this.obj= Arrays.copyOf(obj,lengthqueue);//扩容
                int i=expansion;
                while(i>0){
                    this.EnQueue();
                    --i;
                }
            }
            return 0;
        }
    }
    public Object DeQueue(){
        Object revalue=null;
        if(!this.isEmpty()){//如果是非空的话
            revalue=obj[this.tail-1];
            obj[this.tail-1]=null;
            --tail;
        }else{
            System.out.println("空队列 无法返回");
        }
        System.out.println("出队元素:"+revalue);
        return revalue;
    }

    @Override
    public String toString() {
        return "queueNode{" +
                "obj=" + Arrays.toString(obj) +
                '}';
    }
}

接口部分

public interface queueNodeinterface {
    boolean  isFull();
    boolean  isEmpty();
    int EnQueue();
    Object DeQueue();
}

测试部分

//队列是指一端进 一端出的线性表
public class queueTest {
    public static void main(String[] args) {
        queueNode q=new queueNode(5);
        System.out.println("检查是否为满队列:"+(q.isFull()?"满队列":"队列未满"));
        System.out.println("检查是否为空队列:"+(q.isEmpty()?"空队列":"队列不空"));
        q.EnQueue();
        q.EnQueue();
        q.EnQueue();
        q.EnQueue();
        q.EnQueue();
        q.EnQueue();
        System.out.println(q.toString());;
    }
}

在这里插入图片描述

链式结构

链表的结点

class Node{
    Object element;
    Node head;//这个用于指向有元素的的第一个结点
    Node tail;//指向尾结点
    //Node next;
    public Node(Object element) {
        this.element = element;
    }

    public Node() {

    }
}

实现部分

class queueNodeLink{
    Node node;
    Object data;
    int size=0;
    public queueNodeLink(){
        InitQueue();
    }
    public void InitQueue(){//生成一个头结点
        node=new Node();
        node.head=null;
        node.tail=null;
        //node.next=null;
        System.out.println("请输入队长的元素");
        Scanner scanner=new Scanner(System.in);
        node.element=scanner.nextLine();
        this.size++;
    }

    public void EnQueue(){
        System.out.println("请输入一个元素:");
        Node n=new Node();//创造一个新的结点
        Scanner scanner=new Scanner(System.in);
        n.element=scanner.nextLine();
        Node tem=node;//我要找到null的上一个结点
        while(tem.tail!=null){
            tem=tem.tail;
        }
        //当tem.tail为空时
        tem.tail=n;
        n.head=tem;
        n.tail=null;
        this.size++;
    }

    public int DeQueue(){
        if(this.isEmpty()){//当队列为空时!
            System.out.println("空队列,无法出队,请选择是否要进行入队操作?------1为进行入队操作,2为终止此处操作");
            Scanner scanner=new Scanner(System.in);
            int s=scanner.nextInt();
            while(s!=1&&s!=2){
                System.out.println("输入错误,重新输入:");
                s=scanner.nextInt();
            }
            if(s==1){
                System.out.println("请选择插入次数:");
                int k=scanner.nextInt();
                while(k<=0){
                    System.out.println("输入错误,重新输入:");
                    k=scanner.nextInt();
                }

                this.InitQueue();
                for (int i = 0; i <k-1 ; i++) {
                    this.EnQueue();
                }
                this.DeQueue();
            }else{
                System.out.println("出队失败!终止***");
                return 0;
            }
        }
        System.out.println("请选择出队个数:");
        Scanner scanner=new Scanner(System.in);
        int d=scanner.nextInt();
        while(d>this.size||d<=0){
            System.out.println("输入错误,请重新输入:");
            d=scanner.nextInt();
        }
        //Node next=node;
        Node temnode=null;
        Object value=null;
        for (int i = 0; i <d; i++) {

            value=node.element;//获取元素
            temnode=node;//存储当前结点
            node=node.tail;//指向下一个
            temnode=null;//释放该结点
            size--;
            System.out.println("出队:"+value);
        }

        return 0;
    }

    public boolean isEmpty(){
        return this.size==0;//size等于0  即为空
    }

    public void Pritqueue(){
        if(!isEmpty()){//队列不空时
            Node t=node;
            for (int i = 0; i <this.size ; i++) {
                System.out.println(t.element);
                t=t.tail;
            }
        }else{
            System.out.println("队列空 无法打印");
        }

    }
}

在这里插入图片描述

1.两个栈实现一个队列

应用两个栈实现一个队列,分析运行时间
算法图解:如何用两个栈实现一个队列?
一开始写的是 实现了如下功能,还出栈的时候转移到另外一个队列中 虽然也没错
但是我理解错了问题的含义
借助栈先进后出的原则
两个栈一起用就实现了先进先出和队列一样
负负得正的意思

在入队列的时候,是将开始入A栈的元素,一起转移到B栈中,所以时间复杂度为O(n)
出队列的时候就是这里也是O(n)
看算法吧 也可以改成只出一个

然后在重新入队列的时候 需要判断一下B栈中是否还有元素

import java.util.Scanner;

public class TwoStacksAQueue {
    public static void main(String[] args) {
        Test t=new Test();
       t.EnQueuebyStacks();
       t.DeQueue();
    }
}
//代码此时有问题 我虽然实现了  栈A入元素,  栈B出元素  且用另外一个队列保存
//但是没有领会到问题所在  两个栈实现队列的功能即可!!!!
//所以此处无需构造队列的实际结点
//栈的结点结构
class NodeStack{
    Object data;//元素
    NodeStack next;//相当于指针  指向下一个
    public NodeStack(){

    }
    public NodeStack(Object data) {
        this.data = data;
        //this.next = next;
    }
}
class Test{
    /*先实现A栈  负责 入元素*/
    NodeStack top;//top一直指向顶点元素
    private int sizeStack;

    public Test(){
        this.InitStackA();
        this.InitStackB();
    }

    public void InitStackA(){
        top=null;
        this.sizeStack=0;
    }

    public boolean isEmptyStackA(){
        return this.sizeStack==0;
    }

    /*对栈A进行入栈操作*/
    //先插入的是栈底
    //top指针始终指向栈顶,所以top紧跟最新的元素
    public void pushStackA(){
        NodeStack nodeAStack=new NodeStack();
        System.out.println("请输入元素入A队列:");
        Scanner scanner=new Scanner(System.in);
        Object obj=scanner.nextLine();
        nodeAStack.data=obj;

        nodeAStack.next=top;
        top=nodeAStack;
        this.sizeStack++;
    }

    public Object popStackA(){
        Object value;
        if(isEmptyStackA()){
            System.out.println("空队列");
            return 0;
        }
        value = top.data;//因为top是指向栈顶的指针
        NodeStack Oldtop=top;
        top=top.next;
        Oldtop=null;
        --sizeStack;
        return value;
    }
    /*实现一个栈 进行出栈操作*/
    //而该栈必须要有元素 所以必须得有入栈步骤  同理 A结点  功能也要有一个出栈操作。

    NodeStack topB;//top一直指向顶点元素
    private int sizeStackB;

    public void InitStackB(){
        topB=null;
        this.sizeStackB=0;
    }
    public boolean isEmptyStackB(){
        return this.sizeStackB==0;
    }
    public void pushStackB(Object obj){
        NodeStack nodeAStackB=new NodeStack();
        //System.out.println("从栈A中开始元素入栈:");
        //obj=this.popStackA();
        nodeAStackB.data=obj;

        nodeAStackB.next=topB;
        topB=nodeAStackB;
        sizeStackB++;
    }

    public Object popStackB(){
        Object value;
        if(isEmptyStackB()){
            System.out.println("空B栈");
            return 0;
        }
        value = topB.data;//因为top是指向栈顶的指针
        NodeStack Oldtop=topB;
        topB=topB.next;
        Oldtop=null;
        sizeStackB--;
        return value;
    }


    //利用栈 实现队列的功能
    //但是这里存在一个问题 如果B栈原本有元素呢
    //那就先使其出栈
    public void EnQueuebyStacks(){
        if(this.isEmptyStackB()){
            for (int i = 0; i < this.sizeStackB; i++) {
                this.DeQueue();
            }
        }
        System.out.println("请输入元素的个数n:");
        Scanner scanner=new Scanner(System.in);
        int num=scanner.nextInt();
        for (int i = 0; i < num; i++) {
            this.pushStackA();
            this.pushStackB(this.popStackA());
        }
    }

    public void DeQueue(){//出队
        int numsize=this.sizeStackB;
        for (int i = 0; i <numsize ; i++) {
            System.out.println("出队列元素为:"+this.popStackB());
        }
    }
}

2.两个队列实现一个栈

队列:先进先出
栈:先进后出

要求:两个队列q1 q2
利用两个队列实现压栈:
直接入队q1就行 这入元素都一样

利用两个队列实现弹/出栈:
情况1:如果队列q1存在元素,则将q1中n-1个元素排入q2中,剩余一个直接弹出
情况2:q1不存在元素,而q2经过之前操作从q1转移了元素,即现在所有元素都在q2中,那么也是将q2中n-1个元素全部排入q1中,剩余一个直接弹出
这样就实现了先进后出的弹栈操作。

同时要注意到 如果出栈时,A队列 B 队列都只有一个元素 ,那么无需转移

import com.sun.corba.se.spi.ior.ObjectKey;
import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport;

import java.util.Scanner;

public class TwoQueueAStack {
    public static void main(String[] args) {
        queueNodeLink q=new queueNodeLink();
        //入栈
        Scanner scanner=new Scanner(System.in);
        Object obj=0;
        System.out.println("******输入需要入栈个数******");
        int num=scanner.nextInt();
        Scanner scanner2=new Scanner(System.in);
        for (int i=0;i<num;i++){
            System.out.println("****请输入入栈元素:****");
            obj=scanner2.nextLine();
            //System.out.println(obj);
            q.EnQueueA(obj);
        }
        //出栈
        q.QueuetoStackEnqueue();
        //q.QueuetoStackEnqueue();
        q.EnQueueA("adsad");
        q.QueuetoStackEnqueue();
        q.QueuetoStackEnqueue();
        q.QueuetoStackEnqueue();
        q.QueuetoStackEnqueue();
        q.QueuetoStackEnqueue();
        q.QueuetoStackEnqueue();
    }
}
class Node{
    Object element;
    Node head;//这个用于指向有元素的的第一个结点
    Node tail;//指向尾结点
    //Node next;
    public Node(Object element) {
        this.element = element;
    }

    public Node() {

    }
}

class queueNodeLink{
    Node node;
    Object data;
    int size=0;
    public queueNodeLink(){

    }
    //初始化A结点  生成一个头结点
    public void InitQueueA(Object obj){
        node=new Node();
        node.head=null;
        node.tail=null;
        node.element=obj;
        this.size++;
    }
    //栈入队,无论队列A 和队列B怎样都是直接A对入队 认为压栈。
    public void EnQueueA(Object obj){
        if(node==null){
            this.InitQueueA(obj);
        }
        else{
            Node n=new Node();//创造一个新的结点
            n.element=obj;
            Node tem=node;//我要找到null的上一个结点
            while(tem.tail!=null){
                tem=tem.tail;
            }
            tem.tail=n;
            n.head=tem;
            n.tail=null;
            this.size++;
        }

    }
    //A队出队
    public Object DeQueueA(){
        Node temnode=null;
        Object value=null;
        value=node.element;//获取元素
        temnode=node;//存储当前结点
        node=node.tail;//指向下一个
        temnode=null;//释放该结点
        size--;
        return value;
    }

    public boolean isEmptyA(){
        return this.size==0;
    }

    /*********开始构造队列B************/
    Node nodeB;
    Object dataB;
    int sizeB=0;

    public boolean isEmptyB(){
        return this.sizeB==0;
    }
    //初始化队列B  生成一个头结点
    public void InitQueueB(Object obj){
        nodeB=new Node();
        nodeB.head=null;
        nodeB.tail=null;
        nodeB.element=obj;
        this.sizeB++;
    }
    //B 队列入列  通过队列A转移  每次转移n-1个
    public void EnQueueStack(){
        while(nodeB==null){
            Object obj=null;
            obj=this.DeQueueA();
            this.InitQueueB(obj);
        }
        Object obj=null;
        int num=this.size-1;
        for (int i = 0; i <num; i++) {//每次转移n-1个
            Node nB=new Node();//创造一个新的结点
            obj=this.DeQueueA();
            nB.element=obj;
            Node tem=nodeB;//我要找到null的上一个结点
            while(tem.tail!=null){
                tem=tem.tail;
            }
            //当tem.tail为空时
            tem.tail=nB;
            nB.head=tem;
            nB.tail=null;
            this.sizeB++;
        }
    }

    //B队列出队
    public Object DeQueueB(){
        Node temnode=null;
        Object value=null;
        value=nodeB.element;//获取元素
        temnode=nodeB;//存储当前结点
        nodeB=nodeB.tail;//指向下一个
        temnode=null;//释放该结点
        sizeB--;
        return value;
    }
    //出栈、
    //还要考虑  A中只有一个元素的时候
    public Object QueuetoStackEnqueue(){
        if(!this.isEmptyA()){//A 不为空时
            if(this.size!=1){
                this.EnQueueStack();//转移n-1个元素到B中
                Object obj=this.DeQueueA();
                System.out.println("出栈元素:"+obj);
                return obj;
            }else{
                Object obj=this.DeQueueA();
                System.out.println("出栈元素:"+obj);
                return obj;
            }

        }else if(!this.isEmptyB())//A空 B不空时  转移
        {
            if(this.size!=1){
                int num=this.sizeB-1;
                for (int i = 0; i <num ; i++) {
                    Object obj=this.DeQueueB();//B 队出元素
                    this.EnQueueA(obj);//入A队
                }
                Object value=this.DeQueueB();//排出最后一个
                System.out.println("出栈元素:"+value);
                return value;
            }else{
                Object value=this.DeQueueB();//排出最后一个
                System.out.println("出栈元素:"+value);
                return value;
            }
        }else{
            System.out.println("全空  无法弹栈");
            return null;
        }
    }
}

在这里插入图片描述

3.Java实现酒店管理系统很基础的版本

4栈实现进制转化

后面四个参考博文
因为栈是先进后出
而在十进制、八进制的转化过程中,是倒着排过来的

 //十进制 转换为八进制  同理可用
    public void BaseConversion(){
        System.out.println("请输入需要转化的十进制数*****");
        Scanner scanner=new Scanner(System.in);
        int convsrsion=scanner.nextInt();
        while(convsrsion!=0){
            this.push(convsrsion%8);
            convsrsion/=8;
        }
        System.out.print("十进制转八进制:");
        while(!this.isEmpty()){
            System.out.print(this.pop());
        }
    }

在这里插入图片描述

5括号匹配检验

刚刚开始做的时候,按照常规的发现在括号比较那 出现问题
一直无法解决
原因只能发现我设定的Object类中没有char方法,而且无法强制转化
在这里插入图片描述
看了博客其他人是在类的定义的时候加了一个
好像涉及泛型
目前的知识盲区 后面肯定可理解

因为我前面的参数和返回类型都是Object类,而char属于八种基本类型,所以这需要自动装箱,char的父类Object是Character
另外这个是泛类型 参考一下 Java_泛型的作用
在这里插入图片描述

以下是解决办法。
方法1:
pop返回类型为Object,而我输入的是字符串转了一次为字符类型
在这里插入图片描述
而后面对比的时候字符串 虽然保存为字符,但是pop保存的类型为Object,就把它强制转换为String,所以做对比的时候做一个取舍 那一步要都是一个类型
在这里插入图片描述
这样就可以解决!

参考Java中char和String的相互转换
方法2:泛类型

import java.util.Scanner;

public class matchStack {
    public static void main(String[] args) {
        StackNodematch stack=new StackNodematch();
        System.out.println(stack.match());

    }
}
class StackNodematch<Item>{
    private class Node{
        Item item;
        Node next;

        public Node(Item item) {
            this.item = item;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "item=" + item +
                    '}';
        }
    }

    private Node top;
    private int size=0;

    public StackNodematch() {
        this.InitStack();
    }

    private void InitStack(){
        this.size=0;
        this.top=null;
    }

    public boolean isEmpty(){
        return this.size==0;
    }
    public void push(Item item){
        Node node=new Node(item);
        node.next=top;
        top=node;
        size++;
    }
    public Item pop(){
        Item value;
        if(isEmpty()){
            System.out.println("空栈");
            return null;
        }
        value = top.item;//因为top是指向栈顶的指针
        Node Oldtop=top;
        top=top.next;
        Oldtop=null;
        size--;
        return value;
    }

    @Override
    public String toString() {
        return "StackNodematch{" +
                "top=" + top +
                '}';
    }

    public boolean match(){
        StackNodematch<Character> s=new StackNodematch<>();
        System.out.println("请输入需要检测的括号:");
        String kuohao;
        Scanner scanner=new Scanner(System.in);
        kuohao=scanner.nextLine();
        char[] c=kuohao.toCharArray();
        for (int i=0;i<kuohao.length();i++){
            System.out.println("此时的字符括号:****"+c[i]);
            switch (c[i]){
                case ')':
                    //String x=String.valueOf('(');
                    //System.out.println(this.pop());
                    if(!s.isEmpty()&&s.pop()=='('){//看了一下 Object里没有char的
                        break;
                    }else {
                        System.out.println("第"+(i+1)+"个元素括号不匹配--->"+c[i]);
                        return false;
                    }
                case ']':
                    if(!s.isEmpty()&&s.pop()=='['){
                        break;
                    }else {
                        System.out.println("第"+(i+1)+"个元素括号不匹配--->"+c[i]);
                        return false;
                    }
                case '}':
                    if(!s.isEmpty()&&s.pop()=='{'){
                        break;
                    }else {
                        System.out.println("第"+(i+1)+"个元素括号不匹配--->"+c[i]);
                        return false;
                    }
                default:
                    s.push(c[i]);
                    if((i)%2==0&&(i+1)==kuohao.length()){
                        System.out.println("第"+(i+1)+"个少对应的括号!");
                        return false;
                    }
                    break;
            }
        }
        return this.isEmpty();
    }
}

在这里插入图片描述
在这里插入图片描述

6迷宫求解

更新中

7表达式求值 & 中缀表达式转后缀表达式

更新中 即逆波兰表达式

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值