• JAVA 链表操作:单链表和双链表


    主要讲述几点:

    一、链表的简介

    二、链表实现原理和必要性

    三、单链表示例

    四、双链表示例

     

    一、链表的简介 

      链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都相应的应用,链表有多种类别,文章针对单链表和双链表进行分析。链表中数据就像被一个链条串联一起,轻易的可以实现数据的访问。

    二、链表实现原理和必要性

      这里只分析单链表和双链表。链表的实现过程是有些许复杂的,但是会带来许多好处。比如现在网购时代到来,商家发快递一般会将商品包装在盒子里并写上地址信息,快递公司就可以通过盒子上的信息找到买家,商品完整到达。如果没有盒子的保护,有可能在途中商品受损。而链表就好比那个写了地址信息的盒子,既保护了商品信息,同时又写好了物流信息。链表之中存在一个HEAD节点,类似“火车头”,只要找到相应HEAD节点,就可以对链表进行操作。此次分析中,HEAD节点只是做数据头,不保存有效数据。

      单链表的实现原理如图:

      

      双链表实现原理:

      

    三、单链表示例  

    ICommOperate<T> 接口操作类:

    package LinkListTest;
    import java.util.Map;
    public interface ICommOperate<T> {
        
        public boolean insertNode(T node) ;
        public boolean insertPosNode(int pos, T node) ;
        public boolean deleteNode(int pos) ;
        public boolean updateNode(int pos, Map<String, Object> map) ;
        public T getNode(int pos, Map<String, Object> map) ;
        public void printLink() ;
    }

    单链表节点:

    package LinkListTest;
    // 单连表节点
    public class SNode {
        private String data;
        private SNode  nextNode;
        public SNode() {
        }
        public SNode(String data) {
            this.data = data;
            this.nextNode = new SNode();
        }
        
        public String getData() {
            return data;
        }
        public void setData(String data) {
            this.data = data;
        }
        public SNode getNextNode() {
            return nextNode;
        }
        public void setNextNode(SNode nextNode) {
            this.nextNode = nextNode;
        }
        @Override
        public String toString() {
            return "SNode [data=" + data + "]";
        }
    }

    单链接操作类:

    package LinkListTest;
    import java.util.HashMap;
    import java.util.Map;
    public class SingleLinkList implements ICommOperate<SNode>{
        private SNode head = new SNode("HEAD") ; // 公共头指针,声明之后不变
        private int size = 0 ;
        public int getSize() {
            return this.size;
        }
    
        /*
         * 链表插入,每次往末端插入
         * */
        @Override
        public boolean insertNode(SNode node) {
            boolean flag = false ; 
            SNode current = this.head ;
            if( this.size==0 ){  // 空链表
                this.head.setNextNode(node) ;
                node.setNextNode(null) ;
            }else{                // 链表内节点
                while( current.getNextNode()!=null ){
                    current = current.getNextNode() ;
                }
                current.setNextNode(node) ;
                node.setNextNode(null) ;
            }
            this.size++ ;
            flag = true ;
            
            return flag;
        }
    
        /*
         * 插入链表指定位置pos,从1开始,而pos大于size则插入链表末端
         * */
        @Override
        public boolean insertPosNode(int pos, SNode node){
            boolean flag = true; 
            SNode current = this.head.getNextNode() ;
            
            if( this.size==0 ){                   // 空链表
                this.head.setNextNode(node) ;
                node.setNextNode(null) ;
                this.size++ ;
            }else if( this.size<pos ){           // pos位置大于链表长度,插入末端
                insertNode(node) ;
            }else if( pos>0 && pos<=this.size) { // 链表内节点
                // 1、找到要插入pos位置节点和前节点
                int find = 0;
                SNode preNode = this.head; // 前节点
                SNode currentNode = current; // 当前节点
                while( find<pos-1 && currentNode.getNextNode()!=null ){
                    preNode = current ;                    // 前节点后移
                    currentNode = currentNode.getNextNode() ; // 当前节点后移
                    find++ ;
                }
    //            System.out.println(preNode);
    //            System.out.println(currentNode);
                // 2、插入节点
                preNode.setNextNode(node);
                node.setNextNode(currentNode);
                this.size++ ;
                System.out.println("节点已经插入链表中");
            }else{
                System.out.println("位置信息错误");
                flag = false ;
            }
            
            return flag;
        }
        
        /*
         * 指定链表的节点pos,删除对应节点。方式:找到要删除节点的前后节点,进行删除。从1开始
         * */
        @Override
        public boolean deleteNode(int pos) {
            boolean flag = false; 
            SNode current = this.head.getNextNode() ;
            if( pos<=0 || pos>this.size || current==null ){
                System.out.println("位置信息错误或链表无信息");
            }else{
                // 1、找到要删除节点的前后节点
                int find = 0;
                SNode preNode = this.head; // 前节点
                SNode nextNode = current.getNextNode(); // 后节点
                while( find<pos-1 && nextNode.getNextNode()!=null ){
                    preNode = current ;                    // 前节点后移
                    nextNode = nextNode.getNextNode() ; // 后节点后移
                    find++ ;
                }
    //            System.out.println(preNode);
    //            System.out.println(nextNode);
                
                // 2、删除节点
                preNode.setNextNode(nextNode);
                System.gc();
                this.size-- ;
                flag = true ;
            }
            
            return flag;
        }
    
        /*
         * 指定链表的节点pos,修改对应节点。 从1开始
         * */
        @Override
        public boolean updateNode(int pos, Map<String, Object> map) {
            boolean flag = false ;
            SNode node = getNode(pos, map); // 获得相应位置pos的节点
            if( node!=null ){
                String data = (String) map.get("data") ;
                node.setData(data);
                flag = true ;
            }
            return flag;
        }
    
        /*
         * 找到指定链表的节点pos,从1开始
         * */
        @Override
        public SNode getNode(int pos, Map<String, Object> map) {
            SNode current = this.head.getNextNode() ;
            if( pos<=0 || pos>this.size || current==null ){
                System.out.println("位置信息错误或链表不存在");
                return null;
            }
            int find = 0 ;
            while( find<pos-1 && current!=null  ){
                current = current.getNextNode() ;
                find++ ;
            }
            return current;
        }
    
        /*
         * 打印链表
         * */
        @Override
        public void printLink() {
            int length = this.size ;
            if( length==0 ){
                System.out.println("链表为空!");
                return ;
            }
            SNode current = this.head.getNextNode() ;
            int find = 0 ; 
            System.out.println("总共有节点数: " + length +" 个");
            while( current!=null ){
                System.out.println("第 " + (++find) + " 个节点 :" + current);
                current=current.getNextNode() ;
            }
        }
        
        public static void main(String[] args) {
            SingleLinkList sll = new SingleLinkList() ;
            SNode node1 = new SNode("节点1");
            SNode node2 = new SNode("节点2");
            SNode node3 = new SNode("节点3");
            SNode node4 = new SNode("节点4");
            SNode node5 = new SNode("节点5");
            SNode node6 = new SNode("插入指定位置");
            sll.insertPosNode(sll.getSize()+1, node1) ;
            sll.insertPosNode(sll.getSize()+1, node2) ;
            sll.insertPosNode(sll.getSize()+1, node3) ;
            sll.insertPosNode(sll.getSize()+1, node4) ;
            sll.insertPosNode(sll.getSize()+1, node5) ;
            
    //        sll.insertNode(node1);
    //        sll.insertNode(node2);
    //        sll.insertNode(node3);
    //        sll.insertNode(node4);
    //        sll.insertNode(node5);
            
            System.out.println("*******************输出链表*******************");
            sll.printLink();
            
            System.out.println("*******************获得指定链表节点*******************");
            int pos = 2 ;
            System.out.println("获取链表第  "+pos+" 个位置数据 :"+sll.getNode(pos, null));
            
            System.out.println("*******************向链表指定位置插入节点*******************");
            int pos1 = 2 ;
            System.out.println("将数据插入第 "+pos1+" 个节点:");
            sll.insertPosNode(pos1, node6) ;
            sll.printLink();
            
            System.out.println("*******************删除链表指定位置节点*******************");
            int pos2 = 2 ;
            System.out.println("删除第 "+pos2+" 个节点:");
            sll.deleteNode(pos2) ;
            sll.printLink();
            
            System.out.println("*******************修改链表指定位置节点*******************");
            int pos3 = 2 ;
            System.out.println("修改第 "+pos3+" 个节点:");
            Map<String, Object> map = new HashMap<>() ;
            map.put("data", "this is a test") ;
            sll.updateNode(pos3, map) ;
            sll.printLink();
        }
    }

     

    四、双链表示例

    ICommOperate<T> 接口操作类:

    package LinkListTest;
    import java.util.Map;
    public interface ICommOperate<T> {   
        public boolean insertNode(T node) ;
        public boolean insertPosNode(int pos, T node) ;
        public boolean deleteNode(int pos) ;
        public boolean updateNode(int pos, Map<String, Object> map) ;
        public T getNode(int pos, Map<String, Object> map) ;
        public void printLink() ;
    }

    双链表节点:

    package LinkListTest;
    // 双连表节点
    public class DNode {
        private DNode  priorNode;
        private String data;
        private DNode  nextNode;
        
        public DNode(){ 
        }
        public DNode(String data) {
            this.priorNode = new DNode() ;
            this.data = data ;
            this.nextNode = new DNode() ;
        }
    
        public DNode getPriorNode() {
            return priorNode;
        }
        public void setPriorNode(DNode priorNode) {
            this.priorNode = priorNode;
        }
    
        public String getData() {
            return data;
        }
        public void setData(String data) {
            this.data = data;
        }
    
        public DNode getNextNode() {
            return nextNode;
        }
        public void setNextNode(DNode nextNode) {
            this.nextNode = nextNode;
        }
    
        @Override
        public String toString() {
            return "DNode [data=" + data + "]";
        }   
    }

     双链表实现类:

    package LinkListTest;
    import java.util.HashMap;
    import java.util.Map;
    public class DoubleLinkList implements ICommOperate<DNode>{
        private DNode head = new DNode("HEAD");
        private int size = 0 ;
        public int getSize() {
            return this.size;
        }
        
        /*
         * 链表插入,每次往末端插入
         * */
        @Override
        public boolean insertNode(DNode node) {
            boolean flag = false; 
            
            DNode current = this.head ;
            if( this.size==0 ){  // 空链表
                this.head.setNextNode(node) ;
                node.setPriorNode(this.head);
                node.setNextNode(null) ;
            }else{                // 链表内节点
                while( current.getNextNode()!=null ){
                    current = current.getNextNode() ;
                }
                current.setNextNode(node);
                node.setNextNode(null);
                node.setPriorNode(current);
            }
            this.size++ ;
            flag = true ;
        
            return flag;
        }
        
        /*
         * 插入链表指定位置pos,从1开始,而pos大于size则插入链表末端
         * */
        @Override
        public boolean insertPosNode(int pos, DNode node) {
            boolean flag = true;
            
            DNode current = this.head.getNextNode() ;
            if( this.size==0){                         // 链表为空
                this.head.setNextNode(node) ;
                node.setNextNode(null) ;
                node.setPriorNode(this.head);
                this.size++ ;
            }else if( pos>this.size ){                 // pos位置大于链表长度,插入末端
                insertNode(node) ;
            }else if( pos>0 && pos<=this.size ){    // 链表内节点
                // 1、找到要插入位置pos节点,插入pos节点当前位置
                int find = 0;
                while( find<pos-1 && current.getNextNode()!=null ){
                    current = current.getNextNode() ;
                    find++ ;
                }
                // 2、插入节点
                if( current.getNextNode()==null ){ // 尾节点
                    node.setPriorNode(current);
                    node.setNextNode(null);
                    current.setNextNode(node);
                } else if( current.getNextNode()!=null ) {  //中间节点
                    node.setPriorNode(current.getPriorNode());
                    node.setNextNode(current);
                    current.getPriorNode().setNextNode(node);
                    current.setPriorNode(node);
                } 
                this.size++ ;
            }else{
                System.out.println("位置信息错误");
                flag = false ;
            }
            
            return flag;
        }
        
        /*
         * 指定链表的节点pos,删除对应节点,从1开始
         * */
        @Override
        public boolean deleteNode(int pos) {
            boolean flag = false; 
            DNode current = this.head.getNextNode() ;
            if( pos<=0 || pos>this.size || current==null ){
                System.out.println("位置信息错误或链表不存在");
            }else{
                // 1、找到要删除位置pos节点
                int find = 0;
                while( find<pos-1 && current.getNextNode()!=null ){
                    current = current.getNextNode() ;
                    find++ ;
                }
                // 2、删除节点
                if( current.getNextNode()==null ){ // 尾节点
                    current.getPriorNode().setNextNode(null) ;
                } else if( current.getNextNode()!=null ) {  //中间节点
                    current.getPriorNode().setNextNode(current.getNextNode()) ;
                    current.getNextNode().setPriorNode(current.getPriorNode()) ;
                } 
                System.gc();
                this.size-- ;
                flag = true ;
            }
            return flag;
        }
    
        /*
         * 指定链表的节点pos,修改对应节点。 从1开始
         * */
        @Override
        public boolean updateNode(int pos, Map<String, Object> map) {
            boolean flag = false ;
            DNode node = getNode(pos, map);
            if( node!=null ){
                String data = (String) map.get("data") ;
                node.setData(data);
                flag = true ;
            }
            return flag;
        }
        
        /*
         * 找到指定链表的节点pos,从1开始
         * */
        @Override
        public DNode getNode(int pos, Map<String, Object> map) {
            DNode current = this.head.getNextNode() ;
            if( pos<=0 || pos>this.size || current==null ){
                System.out.println("位置信息错误或链表不存在");
                return null;
            }
            int find = 0 ;
            while( find<pos-1 && current!=null  ){
                current = current.getNextNode() ;
                find++ ;
            }
            return current;
        }
        
        /*
         * 打印链表
         * */
        @Override
        public void printLink() {
            int length = this.size ;
            if( length==0 ){
                System.out.println("链表为空!");
                return ;
            }
            DNode current = this.head.getNextNode() ;
            int find = 0 ; 
            System.out.println("总共有节点数: " + length +" 个");
            while( current!=null ){
                System.out.println("第  " + (++find) + " 个节点 :" + current);
                current=current.getNextNode() ;
            }
        }
        
        public static void main(String[] args) {
            DoubleLinkList dll = new DoubleLinkList() ;
            DNode node1 = new DNode("节点1");
            DNode node2 = new DNode("节点2");
            DNode node3 = new DNode("节点3");
            DNode node4 = new DNode("节点4");
            DNode node5 = new DNode("节点5");
            DNode node6 = new DNode("插入指定位置");
            dll.insertPosNode(10, node1) ;
            dll.insertPosNode(10, node2) ;
            dll.insertPosNode(10, node3) ;
            dll.insertPosNode(10, node4) ;
            dll.insertPosNode(10, node5) ;
    //        dll.insertNode(node1);
    //        dll.insertNode(node2);
    //        dll.insertNode(node3);
    //        dll.insertNode(node4);
    //        dll.insertNode(node5);
            
            System.out.println("*******************输出链表*******************");
            dll.printLink();
            
            System.out.println("*******************获得指定链表节点*******************");
            int pos = 2 ;
            System.out.println("获取链表第  "+pos+" 个位置数据 :"+dll.getNode(pos, null));
            
            System.out.println("*******************向链表指定位置插入节点*******************");
            int pos1 = 2 ;
            System.out.println("将数据插入第"+pos1+"个节点:");
            dll.insertPosNode(pos1, node6) ;
            dll.printLink();
            
            System.out.println("*******************删除链表指定位置节点*******************");
            int pos2 = 7 ;
            System.out.println("删除第"+pos2+"个节点:");
            dll.deleteNode(pos2) ;
            dll.printLink();
            
            System.out.println("*******************修改链表指定位置节点*******************");
            int pos3 = 2 ;
            System.out.println("修改第"+pos3+"个节点:");
            Map<String, Object> map = new HashMap<>() ;
            map.put("data", "this is a test") ;
            dll.updateNode(pos3, map) ;
            dll.printLink();
        } 
    }
  • 相关阅读:
    javascript获取本地机器信息
    js中获取日期格式
    C#.NET 对HashTable数组进行按值排序
    c# 修饰符
    Android浏览器软键盘中的回车(确认)会触发表单提交的问题解决办法
    excel 选择一个单元格,高亮一行
    Berkeley Language Model
    [转]sqlserver2005 【用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联】解决方案
    Berkeley Parser
    自然语言处理(NLP)网上资源整理 (转)
  • 原文地址:https://www.cnblogs.com/xiaoxing/p/5969133.html
Copyright © 2020-2023  润新知