Java實現單鏈表

單鏈表是最基本的數據結構之一,之前在學數據結構的時候用C語言寫過單鏈表,但是還從來沒用Java寫過,嘗試之後才發現Java用對象實現起來雖然沒有C那麼簡便快捷,但是卻更加靈活。

定義Link鏈表類

這裏我是用內部類來定義每一個鏈表的節點Node,先定義基本的框架,其餘的方法下面一一添加。

class Link{
    /**
     * 定義鏈表節點,爲了方便數據訪問所以我用內部類
     * */
    private class Node{
        private Object data;
        private Node next;
        public Node(Object data){
            this.data = data;
        }
    }

    private Node root;  // 鏈表根節點
    private int count = 0; // 保存元素的個數
    private int foot = 0;   // 保存鏈表的索引
    private Object[] resArray; // 返回對象數組
}

鏈表添加數據

定義Node類中添加void addNode(Node newNode)方法

    /**
     * 增加新節點
     * @param newNode 新的Node對象
     */
    public void addNode(Node newNode){
        if(this.next == null){
            this.next = newNode;
        }else{  // 向後繼續保存
            this.next.addNode(newNode);
        }
    }

在Link類添加void add(Object obj)方法

    /**
     * 向鏈表中添加元素
     * @param data 添加的數據
     * */
    public void add(Object data) {
        if (data == null) {
            return;
        } else {
            Node newNode = new Node(data);
            if (this.root == null) {
                this.root = newNode;
            } else {
                this.root.addNode(newNode);
            }
        }
        this.count ++;
    }

獲取鏈表長度

Link類中添加方法int size();

    /**
     * 獲取鏈表的長度
     * @return int
     * */
    public int size(){
        return this.count;
    }

判斷鏈表是否爲空

Link類中添加方法boolean isEmpty();

    /**
     * 判斷鏈表是否爲空
     * @return boolean
     * */
    public boolean isEmpty() {
        if (root == null) return true;
        return false;
    }

查找數據是否存在

在Node類中添加方法boolean containsNode(Object obj)

    /**
     * 查詢數據是否存在於節點中
     * @param data
     * @return boolean
     */
    public boolean containsNode(Object data){
        if(this.data.equals(data)){
            return true;
        }else{
            if(this.next == null){
                return false;
            }else {
                return this.next.containsNode(data);
            }
        }
    }

在Link類中添加方法boolean contains(Object obj)

    /**
     * 根據節點內容判斷某一個數據是否存在
     * @return boolean
     * */
    public boolean contains(Object data){
        if (data == null || this.root == null) return false;
        return this.root.containsNode(data);
    }

根據索引取得數據

在Node類中添加方法Object getNode(int index)

    /**
     * 獲取某一索引的節點數據
     * @param index 索引
     * @return Object
     */
    public Object getNode(int index) {
        // 使用當前節點索引與index比較,隨後自增,目的是爲了下一步查詢
        if(Link.this.foot ++ == index){ // 如果當前節點索引與index相等就返回當前節點的data
            return this.data;
        }else{
            return this.next.getNode(index);
        }
    }

在Link類中添加方法Object get(int index)

    /**
     * 根據索引取得數據
     * */
    public Object get(int index) {

        if(index+1 > this.count){
            try {
                throw new Exception("索引值超出鏈表長度!");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }else{
            this.foot = 0;
            return this.root.getNode(index);
        }
    }

根據索引值修改鏈表內容

在Node類添加方法void setNode(int index, Object data)

    /**
     * 根據索引值設置節點內容
     * @param index 索引
     * @param data 數據
     */
    public void setNode(int index, Object data) {
        if(Link.this.foot ++ == index){
            this.data = data;
        }else {
            this.next.setNode(index,data);
        }
    }

在Link類添加方法void set(int index,Object data)

    /**
     * 根據索引值修改節點內容
     * @param index 節點索引
     * @param data 節點數據
     */
    public void set(int index,Object data){
        if(index+1 > this.count){
            try {
                throw new Exception("索引值超出鏈表長度!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {
            this.foot = 0;
            this.root.setNode(index,data);
        }
    }

打印鏈表所有內容

在Node類裏添加void printNode()

    /**
     * 打印出節點數據內容
     * @return
     */
    public void printNode() {
        System.out.println(this.data);
        if(this.next != null){
            this.next.printNode();
        }
    }

在Link類裏添加void print()

    /**
     * 打印鏈表所有內容
     */
    public void print(){
        this.foot =0;
        if (this.count != 0){
            this.root.printNode();
        }
    }

根據數據內容刪除節點

在Node類中添加方法void removeNode(Node previous, Object data)

    /**
     * 根據索引值刪除節點
     * @param index
     */
    public void removeNode(Node previous, Object data) {
        if(this.data == data){
            previous.next = this.next;
        }else {
             this.next.removeNode(this,data);
        }
    }

在Link類中添加方法void remove(Object data)

    /**
     * 根據數據內容刪除節點
     * @param index
     */
    public void remove(Object data){
        if (!this.contains(data)){
            try {
                throw new Exception("鏈表內不存在該數據!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else if(data.equals(this.root.data)){
            this.root = this.root.next;
        }else{
            this.root.next.removeNode(this.root,data);
        }
        this.count --;
    }

返回對象數組

在Link類中添加方法Object[] toArray()

    /**
     * 將鏈表以對象數組形式返回
     * @return
     */
    public Object[] toArray(){
        if(this.root == null){
            return null;
        }
        this.resArray = new Object[this.count];
        this.foot = 0;
        while(this.foot != this.count){
            resArray[this.foot] = this.get(this.foot);
        }
        return resArray;
    }

測試鏈表

我們在main方法中對上面鏈表的增、刪、改、查進行測試

public class LinkDemo {
    public static void main(String[] args) {
//        new 一個鏈表對象
        Link link = new Link();
        System.out.println("--------------------添加數據前-----------------");
        System.out.println("鏈表是否爲空:"+link.isEmpty());
        System.out.println("鏈表的長度:"+link.size());

//        向鏈表中添加一個字符串對象
        link.add("A");
//        向鏈表中添加一個char型數據
        link.add('B');
//        向鏈表中添加一個Boolean對象
        link.add(true);
//        向鏈表中添加一個int型數據
        link.add(123);
//        向鏈表中添加一個集合對象
        ArrayList arrayList = new ArrayList<String>();
        arrayList.add("hello");
        arrayList.add("world");
        arrayList.add("!");
        link.add(arrayList);
        System.out.println("--------------------添加數據後-----------------");
//        判斷是否爲空
        System.out.println("鏈表是否爲空:"+link.isEmpty());
//        獲取鏈表長度
        System.out.println("鏈表的長度:"+link.size());
//        根據索引值獲取某一個節點數據
        System.out.println("獲取第2個節點的數據:"+link.get(1));
//        修改第一個節點數據爲tianzhi
        link.set(0,"tianzhi");
        System.out.println("修改第1個節點數據爲tianzhi後第1個節點:"+link.get(0));
        System.out.println("************刪除節點內容值爲true之前************");
        link.print();
//        刪除節點內容值爲true的節點
        link.remove(true);
        System.out.println("************刪除節點內容值爲true之後************");
        link.print();
//        返回對象數組
        System.out.println("++++++++++++以下是對象數組輸出++++++++++++");
        for (int i = 0;i<link.toArray().length;i++){
            System.out.println(link.toArray()[i]);
        }
//        測試節點長度越界情況
        System.out.println("############以下是測試鏈表越界############");
        link.get(100);
    }
}

最終輸出結果:

--------------------添加數據前-----------------
鏈表是否爲空:true
鏈表的長度:0
--------------------添加數據後-----------------
鏈表是否爲空:false
鏈表的長度:5
獲取第2個節點的數據:B
修改第1個節點數據爲tianzhi後第1個節點:tianzhi
************刪除節點內容值爲true之前************
tianzhi
B
true
123
[hello, world, !]
************刪除節點內容值爲true之後************
tianzhi
B
123
[hello, world, !]
++++++++++++以下是對象數組輸出++++++++++++
tianzhi
B
123
[hello, world, !]
############以下是測試鏈表越界############
java.lang.Exception: 索引值超出鏈表長度!
	at language.Link.get(LinkDemo.java:157)
	at language.LinkDemo.main(LinkDemo.java:277)

單鏈表全部代碼

package language;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author beifengtz
 * @Date Created in 23:07 2018/9/22
 * @Description:
 */
class Link{

    /**
     * 定義鏈表節點
     * */
    private class Node{
        private Object data;
        private Node next;
        public Node(Object data){
            this.data = data;
        }

        /**
         * 增加新節點
         * @param newNode 新的Node對象
         */
        public void addNode(Node newNode){
            if(this.next == null){
                this.next = newNode;
            }else{  // 向後繼續保存
                this.next.addNode(newNode);
            }
        }

        /**
         * 查詢數據是否存在於節點中
         * @param data
         * @return boolean
         */
        public boolean containsNode(Object data){
            if(this.data.equals(data)){
                return true;
            }else{
                if(this.next == null){
                    return false;
                }else {
                    return this.next.containsNode(data);
                }
            }
        }

        /**
         * 獲取某一索引的節點數據
         * @param index 索引
         * @return Object
         */
        public Object getNode(int index) {
//            使用當前節點索引與index比較,隨後自增,目的是爲了下一步查詢
            if(Link.this.foot ++ == index){ // 如果當前節點索引與index相等就返回當前節點的data
                return this.data;
            }else{
                return this.next.getNode(index);
            }
        }

        /**
         * 根據索引值設置節點內容
         * @param index 索引
         * @param data 數據
         */
        public void setNode(int index, Object data) {

            if(Link.this.foot ++ == index){
                this.data = data;
            }else {
                this.next.setNode(index,data);
            }
        }

        /**
         * 打印出節點數據內容
         * @return
         */
        public void printNode() {
            System.out.println(this.data);
            if(this.next != null){
                this.next.printNode();
            }
        }

        /**
         * 根據索引值刪除節點
         * @param index
         */
        public void removeNode(Node previous, Object data) {
            if(this.data == data){
                previous.next = this.next;
            }else {
                this.next.removeNode(this,data);
            }
        }
    }

    private Node root;  // 鏈表根節點
    private int count = 0; // 保存元素的個數
    private int foot = 0;   // 保存鏈表的索引
    private Object[] resArray; // 返回的對象數組
    /**
     * 向鏈表中添加元素
     * @param data 添加的數據
     * */
    public void add(Object data) {
        if (data == null) {
            return;
        } else {
            Node newNode = new Node(data);
            if (this.root == null) {
                this.root = newNode;
            } else {
                this.root.addNode(newNode);
            }
        }
        this.count ++;
    }
    /**
     * 獲取鏈表的長度
     * @return int
     * */
    public int size(){
        return this.count;
    }

    /**
     * 判斷鏈表是否爲空
     * @return boolean
     * */
    public boolean isEmpty() {
        if (root == null) return true;
        return false;
    }

    /**
     * 根據節點內容判斷某一個數據是否存在
     * @return boolean
     * */
    public boolean contains(Object data){
        if (data == null || this.root == null) return false;
        return this.root.containsNode(data);
    }
    /**
     * 根據索引取得數據
     * */
    public Object get(int index) {

        if(index+1 > this.count){
            try {
                throw new Exception("索引值超出鏈表長度!");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }else{
            this.foot = 0;
            return this.root.getNode(index);
        }
    }

    /**
     * 根據索引值修改節點內容
     * @param index 節點索引
     * @param data 節點數據
     */
    public void set(int index,Object data){
        if(index+1 > this.count){
            try {
                throw new Exception("索引值超出鏈表長度!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {
            this.foot = 0;
            this.root.setNode(index,data);
        }
    }

    /**
     * 打印鏈表所有內容
     */
    public void print(){
        this.foot =0;
        if (this.count != 0){
            this.root.printNode();
        }
    }

    /**
     * 根據數據內容刪除節點
     * @param index
     */
    public void remove(Object data){
        if (!this.contains(data)){
            try {
                throw new Exception("鏈表內不存在該數據!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else if(data.equals(this.root.data)){
            this.root = this.root.next;
        }else{
            this.root.next.removeNode(this.root,data);
        }
        this.count --;
    }

    /**
     * 將鏈表以對象數組形式返回
     * @return
     */
    public Object[] toArray(){
        if(this.root == null){
            return null;
        }
        this.resArray = new Object[this.count];
        this.foot = 0;
        while(this.foot != this.count){
            resArray[this.foot] = this.get(this.foot);
        }
        return resArray;
    }
}
public class LinkDemo {
    public static void main(String[] args) {
//        new 一個鏈表對象
        Link link = new Link();
        System.out.println("--------------------添加數據前-----------------");
        System.out.println("鏈表是否爲空:"+link.isEmpty());
        System.out.println("鏈表的長度:"+link.size());

//        向鏈表中添加一個字符串對象
        link.add("A");
//        向鏈表中添加一個char型數據
        link.add('B');
//        向鏈表中添加一個Boolean對象
        link.add(true);
//        向鏈表中添加一個int型數據
        link.add(123);
//        向鏈表中添加一個集合對象
        ArrayList arrayList = new ArrayList<String>();
        arrayList.add("hello");
        arrayList.add("world");
        arrayList.add("!");
        link.add(arrayList);
        System.out.println("--------------------添加數據後-----------------");
//        獲取鏈表長度
        System.out.println(link.size());
//        判斷是否爲空
        System.out.println("鏈表是否爲空:"+link.isEmpty());
        System.out.println("鏈表的長度:"+link.size());
//        根據索引值獲取某一個節點數據
        System.out.println("獲取第2個節點的數據:"+link.get(1));
//        修改第一個節點數據爲tianzhi
        link.set(0,"tianzhi");
        System.out.println("修改第1個節點數據爲tianzhi後第1個節點:"+link.get(0));
        System.out.println("************刪除節點內容值爲true之前************");
        link.print();
//        刪除節點內容值爲true的節點
        link.remove(true);
        System.out.println("************刪除節點內容值爲true之後************");
        link.print();
//        返回對象數組
        System.out.println("++++++++++++以下是對象數組輸出++++++++++++");
        for (int i = 0;i<link.toArray().length;i++){
            System.out.println(link.toArray()[i]);
        }
//        測試節點長度越界情況
        System.out.println("############以下是測試鏈表越界############");
        link.get(100);
    }
}

我的個人博客地址:blog.beifengtz.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章