单向链表是一种线性表,实际上是由节点(Node)组成的,一个链表拥有不定数量的节点。其数据在内存中存储是不连续的,它存储的数据分散在内存中,每个结点只能也只有它能知道下一个结点的存储位置。由N各节点(Node)组成单向链表,每一个Node记录本Node的数据及下一个Node。向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的。



类型Node上不存在属性attributes_System


Java代码1

import lianbiao.MyLink.Node;

public class SingleList {

    //  由于类中的静态方法不能直接调用动态方法,所以将Node内部类修饰为静态类
    public static class Node{
        public int data;
        public Node next;

        public Node(){}

        public Node(int data){
            this.data = data;
            this.next = null;
        }

        public int getData() {
            return this.data;
        }

        public void setData(int data) {
            this.data = data;
        }

        public Node getNext() {
            return this.next;
        }

        public void setNext(Node next) {
            this.next = next;
        }       

    }

    //对头结点的初始化,如果不初始化,将会空指针异常,无法进行以下Node temp=head; temp.next的操作 
    public Node head = new Node(2);

    //count用来统计链表的长度
    public int count;

    public SingleList(){}

    /**
     * 统计链表中结点的个数
     * @return
     */
    public int size(){
        return this.count;
    }

    /**
     * 判断链表是否为空
     * @return
     */
    public boolean isEmpty(){
        return this.head == null ? true : false;
    }


    /**
     * 增加一个结点
     * @param node
     * 在链表的最后插入新的结点
     * 将原本最后一个结点的next指向新结点
     */
    public void addNode(Node node){
        //一个移动的指针(把头结点看做一个指向结点的指针)      
        Node temp=head;

        //遍历单链表,直到遍历到最后一个则跳出循环
        while(temp.next != null){
            //往后移一个结点,指向下一个结点。
            temp=temp.next;
        }
        //temp为最后一个结点,将其next指向新结点
        temp.next=node;
        //统计结点的个数       
        count++;
    }

    /**
     * 在指定位置插入结点
     * @param index
     * @param node
     */
    public void insertNodeByIndex(int index,Node node){
        if(index<1 || index>this.count){
            System.out.println(count);
            System.out.println("插入的位置不合理");
            return ;
        }

        //记录我们遍历到第几个结点了,也就是记录位置。
        int length = 1; 

        //可移动的指针
        //我们的temp代表的是当前位置的前一个结点。
        //前一个结点        当前位置        后一个结点
        //temp    temp.next     temp.next.next

        Node temp = head;

        //遍历单链表
        while(head.next != null){

            //判断是否到达指定位置
            if(index == length){ 
                //结点插入操作
                node.next = temp.next;            
                temp.next = node; 
                count++;
                return;
            }
            length++;
            temp = temp.next;
        } 
    }

    /**
     * 删除某个位置的结点
     * @param index
     */
    public void deleteNodeByIndex(int index){
        if(index<1 || index>=this.count){
            System.out.println("给定的位置不合理");
            return ;
        }

        int length=1;
        Node temp = head;
        while(temp.next != null){
            if(index == length){
                //结点删除操作
                temp.next = temp.next.next;
                count--;
                return;
            }
            length++;
            temp = temp.next;
        }
    }

    /**
     * 某个数据是否在链表中 
     * @param data
     * @return
     */
    public boolean isContain(int data){
        //flag为函数标记,用来表示函数执行的结果
        boolean flag=false;

        //temp为头结点  tail为头结点的下一个结点      
        Node temp=head;
        Node tail=head.next;

        if(temp == null){
            System.out.println("该链表是空链表!");
            flag = false;
        }
        else{
            while(tail != null){
                if(tail.data==data){
                    flag = true;
                    break;
                }
                temp = tail;
                tail = tail.next;
            }
        }       
        return flag;
    }

    public void print(){
        Node temp=head.next;
        System.out.print("链表遍历结果为:  ");
        while(temp != null){
            System.out.print(temp.data+" ");
            temp = temp.next;
        }
        System.out.println();
    }   

    public static void main(String[] args) {

        SingleList list = new SingleList();
        /*SingleList.Node nodes = new Node(7)是对链表头结点的初始化操作
        初始化值的大小不影响最终的函数运行结果
        如果不进行初始化操作,nodes为null,无法调用链表的长度,添加结点等函数操作*/
        SingleList.Node nodes = new Node(7);
        System.out.println(list.isEmpty());
        System.out.println("链表的长度为:"+list.size());
        System.out.println("==================");

        SingleList.Node nodes1 = new Node(2);
        SingleList.Node nodes2 = new Node(2);
        SingleList.Node nodes3 = new Node(6);

        list.addNode(nodes);
        list.insertNodeByIndex(1, nodes1);
        list.insertNodeByIndex(5, nodes2);
        System.out.println(list.isEmpty());
        System.out.println("链表的长度为:"+list.size());
        System.out.println("==================");

        list.addNode(nodes3);
        System.out.println(list.isEmpty());
        System.out.println("链表的长度为:"+list.size());
        System.out.println("==================");

        list.deleteNodeByIndex(4);
        System.out.println(list.isEmpty());
        System.out.println("链表的长度为:"+list.size());
        System.out.println("==================");

        list.print();
        System.out.println("链表中是否存在2这个元素:"+list.isContain(2));
        System.out.println("链表中是否存在5这个元素:"+list.isContain(5));
        System.out.println("链表中是否存在6这个元素:"+list.isContain(6));      
    }
}


程序运行结果:
false
链表的长度为:0
==================
2
插入的位置不合理
false
链表的长度为:2
==================
false
链表的长度为:3
==================
给定的位置不合理
false
链表的长度为:3
==================
链表遍历结果为:  2 7 6 
链表中是否存在2这个元素:true
链表中是否存在5这个元素:false
链表中是否存在6这个元素:true

Java代码2

import lianbiao.SingleList.Node;

public class MyLink {
    //定义链表头结点
    Node head = null; 

    static class Node {

        // 节点的引用,指向下一个节点
        Node next = null;
        // 节点的对象,即数据域
        int data;
        Node(){}

        public Node(int data) {
            this.data = data;
        }
    }

    /**
     * 增加一个结点
     * @param d
     */
    public void addNode(int d) {
        // 实例化一个节点
        Node newNode = new Node(d);
        if (head == null) {
            head = newNode;
            return;
        }

        //一个移动的指针(把头结点看做一个指向结点的指针)
        Node tmp = head;
        while (tmp.next != null) {
            tmp = tmp.next;
        }

        //temp为最后一个结点,将其next指向新结点
        tmp.next = newNode;
    }

    public void insertNodeByIndex(int index,Node node){
        if (index < 1 || index > length()) {
            System.out.println("插入的位置不合理");
            return ;
        }

        int i=1;
        Node preNode = head;
        Node curNode = preNode.next;
        //遍历单链表
        while(curNode != null){

            //判断是否到达指定位置
            if(i == index){ 
                //结点插入操作
                node.next = curNode;            
                preNode.next = node;
                return;
            }
            preNode = curNode;
            curNode = curNode.next;
            i++;
        } 
    }

    /**
     * @param index:删除第index个节点
     * @return
     */
    public boolean deleteNode(int index) {
        if (index < 1 || index > length()) {
            return false;
        }


        if (index == 1) {
            head = head.next;
            return true;
        }

        //i表示第i个位置
        int i = 1;
        Node preNode = head;
        Node curNode = preNode.next;

        //循环遍历寻找第i个结点的位置
        while (curNode != null) {
            if (i == index) {
                preNode.next = curNode.next;
                return true;
            }
            preNode = curNode;
            curNode = curNode.next;
            i++;
        }
        return false;
    }

    /**
     * 链表长度
     * @return 返回节点长度
     */
    public int length() {
        int length = 0;
        Node tmp = head;
        while (tmp != null) {
            length++;
            tmp = tmp.next;
        }
        return length;
    }

    /**
     * 某个数据是否在链表中 
     * @param data
     * @return
     */
    public boolean isContain(int data){
        //flag为函数标记,用来表示函数执行的结果
        boolean flag=false;

        //temp为头结点  tail为头结点的下一个结点      
        Node temp=head;
        Node tail=head.next;

        if(temp == null){
            System.out.println("该链表是空链表!");
            flag = false;
        }
        else{
            while(tail != null){
                if(tail.data==data){
                    flag = true;
                    break;
                }
                temp = tail;
                tail = tail.next;
            }
        }       
        return flag;
    }

    /**
     * 打印链表
     */
    public void printList() {
        Node tmp = head;
        while (tmp != null) {
            System.out.print(tmp.data+" ");
            tmp = tmp.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        MyLink list = new MyLink();
        System.out.println("链表的长度为:" + list.length());
        System.out.println("================");

        list.addNode(5);
        list.addNode(3);
        list.addNode(1);
        list.addNode(2);
        list.addNode(55);
        list.addNode(36);
        System.out.println("链表的长度为:" + list.length());
        System.out.println("头结点的数据域为:" + list.head.data);
        System.out.print("链表打印结果为:");        
        list.printList();

        System.out.println("================");
        list.deleteNode(4);
        System.out.print("After deleteNode(4):");
        System.out.print("链表打印结果为:");
        list.printList();

        System.out.println("================");
        //如果不使用list.insertNodeByIndex(3, new Node(25))代码,Node内部类将不用定义为静态内部类
        list.insertNodeByIndex(3, new Node(25));
        System.out.println("链表的长度为:" +list.length());
        System.out.print("链表打印结果为:");
        list.printList();

        System.out.println("================");
        System.out.println("链表是否包含数据域为25的结点:"+list.isContain(25));
        System.out.println("链表是否包含数据域为10的结点:"+list.isContain(10));
    }
}

程序运行结果:
链表的长度为:0
================
链表的长度为:6
头结点的数据域为:5
链表打印结果为:5 3 1 2 55 36 
================
After deleteNode(4):链表打印结果为:5 3 1 2 36 
================
链表的长度为:6
链表打印结果为:5 3 1 25 2 36 
================
链表是否包含数据域为25的结点:true
链表是否包含数据域为10的结点:false