zoukankan      html  css  js  c++  java
  • 链表、队列、栈

    一、单链表

    所谓单链表(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());
    
            //最常见的栈应用  递归函数调用
            // 队列的应用:消息队列,订阅,线上排队买票
        }
    }
    
  • 相关阅读:
    搜索二维矩阵 240
    238 除自身以外数组的乘积 左右乘积数组
    160 相交链表
    152乘积最大子数组 dp
    leetcode 739 每日温度 单调栈
    543求二叉树的直径
    IOS 支付相关
    Intellij IDEA--can't use subversion command line client : svn
    每日日报34——通过SQL语句将某个字段的括号给去掉
    每日日报33——VisualStudio2013代码格式化快捷键+给窗体添加按钮
  • 原文地址:https://www.cnblogs.com/zzk201/p/13883950.html
Copyright © 2011-2022 走看看