zoukankan      html  css  js  c++  java
  • 数据结构和算法单向链表一之单向链表的简单实现

      链表在我们java中也是一种基础的数据结构,可以理解成是一种和数组同级的数组结构,正如我们所知,在我们使用这集合ArrayList和LinkedList的时候,总会学习底层数组实现的ArrayList和双向链表实现的LinkedList的区别。在这里,我们将要讲说的是单向链表的简单实现,让我们体会一下链表在实现增删改查的时候是怎么样的一个操作,在和前边涉及到的数组的增删改查进行对比,得到我们学习的结论,数组的增删效率低于链表结构,查改效率高于链表结构!

      什么叫做单向链表,我们可以理解为一个一个节点链接起来的一条链子,从第一个开始有指向下一个的箭头,也就是说单向链表的每一个节点我们可以理解为是一个对象,里面包含了date内容属性,同时也包含了next下一个对象的属性。代码如下:

    public class MyList {
        //定义一个头节点
        private Node head;
        //定义一个节点内部类
        class Node{
            int date;
            Node next;
            public Node(int date){
                this.date = date;
            }
        }
        /**
         * 获取链表的长度
         * @return
         */
        public int getSize(){
            //判断是否头结点为空
            if(head == null){
                return 0;
            }else {
                Node current = head;
                int size = 1;
                while((current = current.next)!=null){
                     size++;
                }
                return size;
            }
        }
        /**
         * 判断链表是否为空
         * @return
         */
        public boolean isEmpty(){
            if(head==null){
                return true;
            }else {
                return false;
            }
        }
        /**
         * 根据节点信息判断是否包含这个节点
         * @param date
         * @return
         */
        public boolean contains(int date){
            //判断头结点是否为空
            if(head==null){
                return false;
            }else {
                for(int i = 0;i < getSize();i++){
                    if(head.date==date){
                        return true;
                    }
                    head = head.next;
                }
                return false;
            }
        }
        /**
         * 根据下角标获取对象的节点
         * @param index
         * @return
         */
        public Node getNode(int index){
            //对index的有效进行判断
            if(index < 0 || index >= getSize()){
                throw new IndexOutOfBoundsException();
            }else {
                int i = 0;
                Node current = head;
                while(i < index){
                    current = current.next;
                    i++;
                }
                return current;
            }
        }
        /**
         * 根据节点内容获取节点对象
         * @param date
         * @return
         */
        public Node getNodeByDate(int date){
            //判断链表是否为空
            if(getSize()==0){
                return null;
            }else {
                for (int i = 0; i < getSize(); i++) {
                    if(getNode(i).date == date){
                        return getNode(i);
                    }
                }
                return null;
            }
        }
        /**
         * 插入头结点
         * @param date
         */
        public void addFirstNode(int date){
            Node node = new Node(date);
            node.next = head;
            head = node;
        }
        /**
         * 在链表尾端插入节点
         * @param date
         */
        public void addLastNode(int date){
            //判断头结点是否为空
            if(head == null){
                addFirstNode(date);
            }else {
                //获取原尾端节点
                Node node = getNode(getSize()-1);
                //获取当前节点
                Node nowNode = new Node(date);
                //建立连接
                node.next = nowNode;
            }
        }
        /**
         * 在任意位置插入节点
         * @param index
         * @param date
         */
        public void addNode(int index,int date){
            //判断index的有效性
            if(index < 0 || index > getSize()){
                throw new IndexOutOfBoundsException();
            }else {
                if(index == 0){
                    addFirstNode(date);
                }else if(index == getSize()){
                    addLastNode(date);
                }else {
                    //获取新的当前节点
                    Node nowNode = new Node(date);
                    //获取上一个节点
                    Node node1 = getNode(index - 1);
                    //获取旧的当前节点
                    Node node2 = getNode(index);
                    //断开原来节点的连接
                    node1.next = nowNode;
                    //建立与node2的连接
                    nowNode.next = node2;
                }
            }
        }
        /**
         * 删除任意位置的节点
         * @param index
         */
        public void deleteNode(int index){
            //判断index的有效性质
            if(index < 0 || index >= getSize()){
                throw new IndexOutOfBoundsException();
            }else {
                //判断是否是头结点
                if(index == 0){
                    head.next = null;
                    head = head.next;
                }else {
                    //获取删除节点的上一个节点
                    Node node1 = getNode(index - 1);
                    //获取当前删除节点
                    Node nowNode = getNode(index);
                    //建立上一个节点和下一个节点的连接
                    node1.next = nowNode.next;
                    //断开删除节点和下一个节点的连接
                    nowNode = nowNode.next;
                }
            }
        }
        /**
         * 打印所有的节点信息
         */
        public void printAll(){
            Node current = head;
            while(current!=null){
                System.out.println(current.date);
                current = current.next;
            }
        }
        /**
         * 打印index以后的所有节点信息
         * @param index
         */
        public void printFromIndex(int index){
            //判断index的有效
            if(index < 0 || index >= getSize()){
                throw new IndexOutOfBoundsException();
            }else {
                //获取当前节点
                Node node = getNode(index);
                while(node!=null){
                    System.out.println(node.date);
                    node = node.next;
                }
            }
            
        }
        /**
         * 进行测试所有的方法
         * @param args
         */
        public static void main(String[] args) {
            MyList list = new MyList();
            list.addFirstNode(1);
            list.addLastNode(2);
            list.addFirstNode(3);
            list.addLastNode(4);
            list.addNode(3, 5);
            list.deleteNode(3);
            list.printAll();
            System.out.println(list.isEmpty());
            System.out.println(list.getSize());
            System.out.println(list.getNodeByDate(1));
            System.out.println(list.getNode(2));
            list.printFromIndex(2);
        }
    }

        在上述代码中就是单向链表的简单实现,总的来说我们需要注意的是在输入数据时候,比如下标,我们需要对下标的合法性就行判断在进行操作,我们应该考虑到多种异常情况,然后也就比较简单了。明天我们将继续讲述关于单向链表的一些简单操作问题,如以下

      1、求单链表中节点的个数

      2、查找单链表中的倒数第k个结点

      3、查找单链表中的中间结点

      4、合并两个有序的单链表,合并之后的链表依然有序

      5、单链表的反转

      6、从尾到头打印单链表

      7、判断单链表是否有环

      8、取出有环链表中,环的长度

      9、单链表中,取出环的起始点

      10、判断两个单链表相交的第一个交点

      

  • 相关阅读:
    tensorflow2.0 GPU和CPU 时间对比
    第一次使用FileZilla Server
    PremiumSoft Navicat 15 for Oracle中文破解版安装教程
    Unmapped Spring configuration files found. Please configure Spring facet or use 'Create Default Context' to add one including all unmapped files.
    ng : 无法加载文件 D: odejs ode_global g.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
    angular
    Github上优秀的go项目
    win10---file explore 中remove quick access folder
    react--useEffect使用
    linux---cat 和 grep 的妙用
  • 原文地址:https://www.cnblogs.com/zslli/p/7990072.html
Copyright © 2011-2022 走看看