链表队列栈

Posted zzk201

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表队列栈相关的知识,希望对你有一定的参考价值。

一、单链表

所谓单链表(Linked)在内存中不连续的一段内存空间,链表的每一个元素是一个节点,每一个节点由数据元素和下一个节点的存储位置组成,链表结构与数组结构最大区别是链表结构的存储内存是不连续的,而数组结构的内存是连续的,链表结构不能与数组结构一样快速查找

? 链表机构操作特点是:添加,删除元素效率高,查询效率低;
? 数组结构特点:添加,删除效率低,查询效率高

链表结构的示意图
技术图片
前驱:该节点的上一个元素的地址

后继:该节点的下一个元素的地址

链表结构中最后一个元素的“后继”为null

public class MyLinked {
    //链表中有节点属性
    Node header;//度过有一个节点,name这个节点就是头结点
    int size;//链表节点的大小

    //节点类 包括节点的数据内容和下一个节点的地址
    class Node<T>{
        //表示节点数据内容
        T data;
        //下一个节点的地址
        Node next;
        public Node(T data){
            this.data=data;
        }

        public T getData(){
            return data;
        }
        public void setData(T data){
            this.data=data;
        }
        public Node getNext(){
            return next;
        }
        public void setNext(Node next){
            this.next=next;
        }
    }

链表实现添加元素
技术图片

/**
 *将元素添加到第一个节点
 */
 public void addFirst(Object obj){
      //创建节点
      Node node=new Node(obj);
      //整体要求:将当前链表的头结点变更为新节点
      //新节点中的后继是原始头节点
      node.next=this.header;
      //将头节点变更
      this.header=node;
      //长度加1
      this.size++;
 }
/**
 *添加到最后
 */
 public void addLast(Object obj){
      Node node=new Node(obj);
      //找到最后一个节点
      Node lastNode=this.header;
      while(lastNode.next!=null){
       lastNode=lastNode.next;
      }
      lastNode.next=node;
      this.size++;
 }
/**
 *将元素添加到指定下标
 */
 public void add(Object obj,int index){
      Node node=new Node(obj);
      //验证index的范围
      if(index<0||index>this.size){
        throw new IndexOutOfBoundsException("下标越界,index不在此链表中");
      }
      //查找指定位置的节点(前一个节点的地址 和当前节点的地址)遍历index-1遍
      //前一个节点
      Node pre=this.header;
      //当前下标的节点
      Node cur;
      for(int i=0;i<index-1;i++){
            pre=pre.next;
      }
      cur=pre.next;
      pre.next=node;
      node.next=cur;
      this.size++;
 }

链表实现删除元素
技术图片


/**
 * 删除第一个节点
 */
 public void removeFirst(){
      //删除第一个节点
      if(this.size==0){
            throw new IllegalArgumentException("没有可删除的元素")
      }
      //让当前节点的“后继”作为头结点
      this.header=header.next;
      this.size--;
 }
/**
 *删除第一个节点
 */
 public void removeLast(){
      //删除是否存在数据
      if(this.size==0){
            throw new IllegalArgumentException("没有需要删除的元素");
      }
      //找到最后一个元素的前一个地址,并将该地址的next改为null
      Node pre=this.header;
      Node cur=this.header;
      while(pre.next!=null){
           pre=cur;
            cur=cur.next;
      }
      //最后一个元素 就是 当前
      pre.next=null;
      size--;
 }

链表实现根据下标 获取指定的节点

/**
 *根据下标 获取指定的节点
 */
 public Node getByIndex(int index){
      if(this.size==0){
            throw new IllegalArgumentException("没有需要查找的元素");
      }
      if(index==0){
            return this.header;
      }
      //查找指定下标的元素
      Node cur=this.header;//从第一个元素开始
      int j=0;
      while(index!=j&&index<this.size){
            //依次往下一个元素查找
            cur=cur.next;
            j++;
      }
      return cur;
 }
      puclic int getSize(){
            return size;
      }
 

2、队列结构

队列结构:基于链表结构的基础上,实现一种“先进先出”的结构,常用操作 入队(put),出队(pop),设置队列的头节点和尾节点
技术图片

public class MyQueue <T>{
    //头结点
    private Node front;
    //尾节点
    private Node tail;
    //大小
    private int size;

    public MyQueue() {
        //头,尾为空
        this.front=this.tail=null;
    }
    class Node{
        private T obj;
        private Node next;

        public Node(T obj) {
            this.obj = obj;
        }

        public T getObj() {
            return obj;
        }

        public void setObj(T obj) {
            this.obj = obj;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }
    /**
     * 入队:将元素添加到队列的尾部
     */
    public void put(T obj){
        //创建节点
        Node node=new Node(obj);
        //如果元素为空 则头就是尾,尾就是头
        if (isEmpty()){
            this.front=this.tail=node;
            return;
        }
        //将新元素的地址 作为尾的next
        this.tail.next=node;
        //将新元素的节点  作为尾节点
        this.tail=node;

        this.size++;
    }
    /**
     * 出队:将元素从队列的头部移除(保持与队列脱离关系)
     */
    public T pop(){
        if (isEmpty()){
            throw new IllegalArgumentException("没有弹出的元素");
        }
        //移除头部元素
        Node popNode=this.front;
        //设置现在的头元素是下一个
        this.front=popNode.next;
        //将弹出的元素next设置为null,与队列脱离关系
        popNode.next=null;
        this.size--;
        //如果没有了素了 则需要设置头尾都是null
        if(this.size<0){
            this.front=this.tail=null;
        }
        return popNode.getObj();
    }
    /**
     * 判断元素是否为空
     */
    public boolean isEmpty(){
        if (this.front==null&&this.tail==null){
            return true;
        }
        return false;
    }
}

3、栈结构

栈(Stack)结构也是常用数据结构之一,它具有“后进先出”的特点
技术图片

public class MyStack<T> {
    //定义一个数组,用于存储元素
    private Object[] obj;
    private int size;

    public MyStack() {
        obj=new Object[10];
        size=0;
    }
      
}
 /**
     * 入栈:假如栈元素
     */
    public void push(T t){
        expandCapacity(size+1);
        obj[size]=t;
        size++;
    }

    /**
     * 返回栈顶元素:peek
     */
    public T peek(){
        if (size>0){
            return (T)obj[size-1];
        }
        return null;
    }
    /**
     * 出栈:返回栈顶元素,并删除该元素
     */
    public T pop(){
        T t=peek();
        if (size>0){
            //将最后一个元素 删除
            obj[size-1]=null;
            size--;
        }
        return t;
    }
    /**
     * 是否为空元素
     */
    public boolean isEmpty(){
        return size==0;
    }
    /**
     * 数组扩容大小:1.5倍
     */
    public void expandCapacity(int size){
        if (obj.length<size){
            //需要扩容
            int length=size*3/2 +1;
            this.obj= Arrays.copyOf(this.obj,length);
        }
    }
}

测试

public class TestStack {
    public static void main(String[] args) {
        //创建栈
        MyStack<String> stack=new MyStack<>();
        stack.push("hello1");
        stack.push("hello2");
        stack.push("hello3");
        //返回栈顶
        System.out.println(stack.peek());
        //出栈并删除
        stack.pop();
        System.out.println(stack.peek());

        //最常见的栈应用  递归函数调用
        // 队列的应用:消息队列,订阅,线上排队买票
    }
}







以上是关于链表队列栈的主要内容,如果未能解决你的问题,请参考以下文章

考研数据结构模板:顺序表链表栈队列

数据结构-栈队列和链表

算法漫游指北(第五篇):栈队列栈结构实现基于列表实现栈基于链表实现栈基于列表实现队列基于链表实现队列

算法漫游指北(第五篇):栈队列栈结构实现基于列表实现栈基于链表实现栈基于列表实现队列基于链表实现队列

数据结构(栈队列链表)

数据结构(栈队列链表)