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、判断两个单链表相交的第一个交点

      

  • 相关阅读:
    wordPress屏蔽中国境内的IP
    中国IP地址大全
    WebGL之点精灵的旋转(Rotation Sprite)
    WebGL之点上添加图片(using texture on point)
    potree--加载二进制格式文件
    potree--如何控制八叉树子节点的显示?
    重启tomcat后,访问登陆接口响应慢--Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [27,572] milliseconds.
    Unirest
    配置规范
    函数编写建议
  • 原文地址:https://www.cnblogs.com/zslli/p/7990072.html
Copyright © 2011-2022 走看看