• 大话数据结构(八)Java程序——双向链表的实现


    线性链表——双向链表

    双向链表定义:

    双向链表(double linked list): 是在单表单的每个结点中,再设置一个指向前驱结点的指针域。因此,在双向链表中的结点都有两个指针域,一个指向前驱,一个指向后继。

    双向链表的存储结构

    typedef struts DulNode{

    Element data;

    Struct DulNode *prior;前驱指针

    Struct DulNode *next;后继指针

    }DulDouble, *DulLinkList;

    双向链表的插入与删除

    双向链表的插入:

    假设结点为s,要将结点插入到结点p和p->next中,我们需要下面几步:

    s.prev = p;

    s.next = p.next;

    p.next.prev = s;

    p.next = s;

    总结起来就是:先搞定s的前驱后继,再搞定后结点的前驱,最后解决前驱结点的后继

    双向链表的删除:

    要删除p结点,只需要两个步骤:

    p.next.prev = p.prev;

    p.prev.next = p.next;

    free(p);

    总结:

    相对于单链表,双向链表多了一个指针域,空间上要占用略多一点,但它有很好的对称性,使得对某个结点的前后结点操作更容易,可以提高算法的时间性能,这是牺牲空间换取的。

    Java程序实现双链表:

    package com.aclie.dataStructe4.sqeList;
    
    public class MyDoubleLinkList {
        private int length =0;//当前长度
        private Node head;//头结点
        private Node tail;//当前结点结点
     
        
        public MyDoubleLinkList(){
            initLink();
        }
        public void initLink(){
            head  = new Node(null);
            tail = new Node(null);
            this.head = tail;
            length++;
        }
        
        //获取链表长度
        public int getSize(){
            return length;
        }
        //判断链表是否为空
        public boolean getEmpty(){
            return getSize()==0;
        }
        //根据索引查找元素  从第一个有效值开始
        public Node getNode(int index){
            Node p;
            if(index < 0 || index > length ){
                System.out.println("参数错误");
            }
            if(index < this.length/2){
                p = this.head;
                for(int i=0; i<index; i++){
                    p = p.next;
                }
            }else{
                p = this.tail;
                for(int i= length; i>index;i--){
                    p = p.prev;
                }
            }
            return p;
        }
        
        public Object getData(int index){
            return getNode(index).data;
        }
        
        //在头结点处插入
        public boolean addHead(Object e){
            //前驱引用为null,后继为node
            Node node = new Node(e, null, this.head);
            //改变头结点的前驱后继
            this.head.prev = node;
            this.head = node;
            if(tail == null){
                tail =  this.head;
            }
            length++;
            return true;
        }
        //在尾结点插入
        public boolean addTail(Object e){
            if(this.head == null){
                this.head = new Node(e,null,null);
                this.tail = this.head;
            }else{
                Node node = new Node(e,this.tail,null);
                this.tail.next = node;
                this.tail = node;
                
            }
            length++;
            return true;
            
        }
        //在指定位置插入元素
        public boolean addData(int index,Object ele){
            if(index <0 || index > this.length){
                System.out.println("参数错误");
            }
            if(this.head == null){
                this.addTail(ele);//用尾插法
            }else{
                if(index == 0){
                    addHead(ele);//用头插法
                }else{
                    Node p = this.getNode(index);//要插入处的结点
                    Node n = p.next;
                    Node node = new Node(ele,p,n);//要插入的结点
                    n.prev = node;
                    p.next = node;
                    length ++;
                    
                }
            }
            
            return true;
        }
    
        public void removeData(int index){
            if(index < 0 || index > length){
                 System.out.println("参数错误");
             }else{
                 Node del = null;
                 if(index == 0){
                     del = this.head;
                     this.head = this.head.next;
                     this.head.prev = null;
                     length--;
                 }else if(index == (length-1)){
                         Node p = this.getNode(index-1);//得到要删除结点的前驱结点
                         del = p.next;//要删除的结点
                         p.next = del.next;
                         if(del.next != null){
                             del.next.prev = p;
                         }
                         del.next = null;
                         del.prev = null;
                         length --;
                         
                         this.tail.next = null;
                         this.tail.prev = p;
                         this.tail = p;
                     }
                 else{
                         Node p = this.getNode(index-1);//要删除结点的前驱结点
                         del = p.next;//要删除的结点
                         p.next = del.next;
                         if(del.next != null){
                             del.next.prev = p;
                         }
                         del.prev = null;
                         del.next = null;
                         length--;
                     }
                 
             }
        }
        //打印所有链表中的元素
        public void print(){
            Node current = this.head;
            while(current != null){
                System.out.println(current.data);
                current = current.next;
            }
        }
        //反向打印链表
        public void reversePrint(){
            Node current = this.tail;
            while(current != null){
                System.out.println(current.data);
                current = current.prev;
            }
        }
        public static void main(String args[]){
            MyDoubleLinkList linkList = new MyDoubleLinkList();
            linkList.addHead("aaaa");
    //        System.out.println(linkList.getData(1));
            linkList.addTail("bbbb");
    //        System.out.println(linkList.getData(3));
            linkList.addData(2, "eeee");
    //        linkList.print();
            linkList.removeData(2);
            linkList.print();
            System.out.println(".....");
            linkList.reversePrint();
        }
        
    }
    class Node{
        Node prev;//指针域中前驱
        Node next;//指针域中后继
        Object data;//数据域
        public Node(Node current){
            prev = current;
            next = current;
        }
        //双链表前驱后继及数字域
        public Node(Object d, Node p,Node n){
            this.data = d;
            this.prev = p;
            this.next = n;
        }
        public Node getPrev() {
            return prev;
        }
        public void setPrev(Node prev) {
            this.prev = prev;
        }
        public Node getNext() {
            return next;
        }
        public void setNext(Node next) {
            this.next = next;
        }
        
    }
  • 相关阅读:
    常见分布式锁的基本实现
    Xen安装部署和基本原理
    Android应用在不同版本间兼容性处理
    Android 在fragment中实现返回键单击提醒 双击退出
    Android使用的webcview中带有音乐播放控件,在关闭或分享时处于界面不可见状态下,声音仍在播放的问题解决
    Android 使用WebView浏览有声音或者视频的网页,关闭WebView之后,声音或者视频不停止的解决办法
    Android 自带Base64加密解密
    Android java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230
    Android 微信SDK图片分享(checkArgs fail, thumbData is invalid)
    Android之Glide获取图片Path和Glide获取图片Bitmap
  • 原文地址:https://www.cnblogs.com/snowwang/p/6074577.html
Copyright © 2020-2023  润新知