数据结构-链表 JAVA语言实现

来源:互联网 发布:比价软件推荐 编辑:程序博客网 时间:2024/05/19 09:37

数据结构-链表 JAVA语言实现

作为一名Android程序员,开始学习数据结构和算法,用JAVA语言写写自己对链表的看法和代码上的实现,如果有问题,麻烦指出,互相学习。

目录

  • 数据结构-链表 JAVA语言实现
      • 目录
    • 1单向链表
      • 1 遍历链表
      • 2 插入元素
      • 3 删除元素
    • 2双向链表
      • 1 遍历元素
      • 2 插入元素
      • 3 删除元素
    • 3循环链表
      • 1 遍历链表
      • 2 插入元素
      • 3 删除元素

  • 单向链表
  • 双向链表
  • 循环链表

1、单向链表

单向链表包含多个结点,每个结点都有一个next指向下一个结点,直到最后一个结点的next指向为null,链表结束。

单向链表结点实体类:

/** * 单向链表 */public class ListNode {    private int data;  //结点的数据    private ListNode next;   //指向下一个结点    public ListNode(int data) {        this.data = data;    }    public int getData() {        return data;    }    public void setData(int data) {        this.data = data;    }    public ListNode getNext() {        return next;    }    public void setNext(ListNode next) {        this.next = next;    }}

1.1 遍历链表

循环遍历每个结点,知道结点的next为null时,当前结点为尾结点。

    /**     * 遍历链表,获取长度     * @param headNode     * @return 链表长度     */    public int listLength(ListNode headNode){        int count = 0;        ListNode currentNode = headNode;        while(currentNode != null){            count ++;            currentNode = currentNode.getNext();        }        return count ;    }

1.2 插入元素

插入元素包括三种情况:

  • 插入到头结点前
  • 插入到链表中间位置
  • 插入到尾结点

    (1)插入到头结点只需要将插入的结点的next指向当前头结点,返回插入结点即可。
    (2)插入到中间或者尾结点,遍历结点直到插入位置的前一个节点,将next指向插入结点,再将插入结点的next指向后一元素(如果插入的结点在最后,后以节点为null)。

 /**     * 插入结点  可以为头 中 尾插入     * @param headNode 当前头结点     * @param insertNode 插入结点     * @param position 插入位置     * @return 返回插入后的头结点     */    public ListNode insertNode(ListNode headNode,ListNode insertNode,int position){        //当当前链表为空,新链表直接为插入的链表        if(headNode == null){            return insertNode;        }        //获取长度        int size = listLength(headNode);        if(position > size + 1 || position < 1){            //插入位置不合法            System.out.println("插入位置不合法!");            return headNode;        }        //链表开头插入        if(position == 1){            insertNode.setNext(headNode);            headNode = insertNode;        }else{            ListNode previousNode = headNode;            int count = 1;            while (count < position -1){                previousNode = previousNode.getNext();                count++;            }            insertNode.setNext(previousNode.getNext());            previousNode.setNext(insertNode);        }        return headNode;    }

1.3 删除元素

删除元素同样区别删除位置:头、中、尾
(1)删除头结点:将头结点next设为null,下一个结点即为新的头结点
(2)删除中间或尾部结点,遍历链表直到删除的位置的前一个结点,同时拿到删除位置的后一个结点,将前一个结点的next指向后一个节点。

/**     * 删除某个结点     * @param headNode 头结点     * @param position 删除位置     * @return 返回头结点     */    public ListNode deleteNode(ListNode headNode,int position){        //当前链表为空,        if(headNode == null){            System.out.print("当前链表为空,不能删除!");            return null;        }        //获取长度        int size = listLength(headNode);        if(position > size  || position < 1){            //删除位置不合法            System.out.println("删除位置不合法!");            return headNode;        }        if (position == 1){            // 删除头结点            ListNode currentNode = headNode.getNext();            headNode = null;            return currentNode;        }else {            ListNode previousNode = headNode;            int count = 1;            while (count < position - 1){                previousNode = previousNode.getNext();                count++;            }            //currentNode为删除的那个结点            ListNode currentNode = previousNode.getNext();            previousNode.setNext(currentNode.getNext());            currentNode = null;        }        return headNode;    }

2、双向链表

双向链表顾名思义就是有两个方向,多一个前驱结点。
双向链表结点的实体类:

/** * 双向链表 */public class DLLNode {    private int data;    private DLLNode next;    private DLLNode previous;    public DLLNode(int data, DLLNode newxt, DLLNode previous) {        this.data = data;        this.next = newxt;        this.previous = previous;    }    public int getData() {        return data;    }    public void setData(int data) {        this.data = data;    }    public DLLNode getNext() {        return next;    }    public void setNext(DLLNode next) {        this.next = next;    }    public DLLNode getPrevious() {        return previous;    }    public void setPrevious(DLLNode previous) {        this.previous = previous;    }}

2.1 遍历元素

与单向链表类似,直接上代码:

 /**     * 获取双向链表长度     * @param headNode 头结点     * @return     */    public int getDllLength(DLLNode headNode) {        int count = 0;        DLLNode current = headNode;        while (current != null) {            current = current.getNext();            count++;        }        return count;    }

2.2 插入元素

与单向链表相似,但是要修改插入元素指向的前驱结点。

/**     * 插入结点     * @param headNode 当前头结点     * @param insertNode 插入的结点     * @param position 插入位置     * @return 插入后的头结点     */    public DLLNode insertDllNode(DLLNode headNode , DLLNode insertNode, int position){        if (headNode == null){            return insertNode;        }        int size = getDllLength(headNode);        if(position < 1 || position > size + 1){            System.out.println("插入位置有误");            return headNode;        }        //插入到首位        if (position == 1){            insertNode.setNext(headNode);            headNode.setPrevious(insertNode);            return insertNode;        }else {            DLLNode previousNode = headNode;            int count = 1;            while (count < position - 1){                previousNode = previousNode.getNext();                count ++;            }            DLLNode currentNode = previousNode.getNext();            if(previousNode.getNext() != null){                //插入的位置在末尾                currentNode.setPrevious(insertNode);            }            insertNode.setNext(currentNode);            previousNode.setNext(insertNode);            insertNode.setPrevious(previousNode);        }        return headNode;    }

2.3 删除元素

/**     * 删除结点     * @param headNode 头结点     * @param position 插入位置     * @return 新链表的头结点     */    public DLLNode deleteNode(DLLNode headNode , int position){        if(headNode == null){            System.out.println("当前链表为空,不能进行删除操作!");            return null;        }        int size = getDllLength(headNode);        if(position < 1 || position > size){            System.out.println("删除位置有误");            return headNode;        }        if(position == 1){            DLLNode currentNode = headNode.getNext();            currentNode.setPrevious(null);            headNode = null;            return currentNode;        }else {            DLLNode currentNode = headNode;            int count = 1;            while (count < position){                currentNode  = currentNode.getNext();                count++;            }            DLLNode previousNode = currentNode.getPrevious();            DLLNode nextNode = currentNode.getNext();            previousNode.setNext(nextNode);            if(nextNode != null){                nextNode.setPrevious(previousNode);            }            currentNode = null;        }        return headNode;    }

3、循环链表

循环链表与单向、双向链表的很大差别是没有null值表示结束,不做判断的话,一直循环下去。
循环链表结点实体类:

/** * 循环链表 */public class CLLNode {    private int data;    private CLLNode next;    public CLLNode(int data) {        this.data = data;    }    public CLLNode(int data, CLLNode next) {        this.data = data;        this.next = next;    }    public int getData() {        return data;    }    public void setData(int data) {        this.data = data;    }    public CLLNode getNext() {        return next;    }    public void setNext(CLLNode next) {        this.next = next;    }}

3.1 遍历链表

通过判断循环后的结点是否为头结点还做出结束循环操作。

    /**     * 循环链表长度     *     * @param headNode 头结点     * @return 长度     */    public int getListLenth(CLLNode headNode) {        int count = 0;        CLLNode currentNode = headNode;        while (currentNode != null) {            currentNode = currentNode.getNext();            count++;            if (currentNode == headNode) {                break;            }        }        return count;    }

3.2 插入元素

循环链表插入与单向链表类似,注意将尾结点指向头结点即可。

    /**     * 尾部插入     *     * @param headNode   头结点     * @param insertNode 插入结点     * @return 返回头结点     */    public CLLNode insertEndNode(CLLNode headNode, CLLNode insertNode) {        CLLNode currentNode = headNode;        while (currentNode.getNext() != headNode) {            currentNode = currentNode.getNext();        }        currentNode.setNext(insertNode);        insertNode.setNext(headNode);        return headNode;    }    /**     * 头部插入     * @param headNode   头结点     * @param insertNode 插入结点     * @return 返回头结点     */    public CLLNode insertStartNode(CLLNode headNode, CLLNode insertNode) {        CLLNode currentNode;        currentNode = headNode;        while (currentNode.getNext() != headNode) {            currentNode = currentNode.getNext();        }        currentNode.setNext(insertNode);        insertNode.setNext(headNode);        return insertNode;    }

3.3 删除元素

    /**     * 删除头结点     *     * @param headNode 头结点     * @return 新头结点     */    public CLLNode deleteStartNode(CLLNode headNode) {        CLLNode currentNode = headNode;        while (currentNode.getNext() != headNode) {            currentNode = currentNode.getNext();        }        CLLNode newHeadNode = headNode.getNext();        currentNode.setNext(newHeadNode);        return newHeadNode;    }    /**     * 删除尾结点     *     * @param headNode 头结点     * @return 新头结点     */    public CLLNode deleteEndNode(CLLNode headNode) {        CLLNode currentNode = headNode;        CLLNode lastNode = headNode;        while (currentNode.getNext() != headNode) {            lastNode = currentNode;            currentNode = currentNode.getNext();        }        currentNode = null;        lastNode.setNext(headNode);        return headNode;    }

循环链表中部的删除、插入于单向链表相似。

完整代码:
http://download.csdn.net/download/z740852294/9947970

原创粉丝点击