java之链表

链表

链表

链表,就像我们生活中的项链一样,一节一节连在一起组成。断了可以链接起来,长了可以剪短。简单来说,链表,由一个个节点组成,并且由线连接起来的。而在程序我们的这个线就被引用域给代替了。链表的节点由数据域和引用域,数据域就是用来存放东西的,而引用域就是用来标记该节点在链表中处于一个位置,用于我们调用查找节点;由于节点的连接方式,或者说,引用域的不同,分为不同的链表;

v 单链表:单链表,只有有一个引用域,指向一个节点;也可以这么来说,单链表就是有一条线连接在一起的;如图:

v 双链表:双链表和单链表,其实差别也不是很大,双链表只是比单链表多了一个指针域,也就是引用域而已;也就是说,该节点不仅可以指向他的前一个节点,也可以指向它的后一个节点,我认为,双链表和单链表,唯一一个区别,或者说是好处,那就是,双链表比单链表查找更加方便。如图:

v 循环双链表:循环双链表的话,和双链表的主要区别是,循环双链表的头节点的上一个节点指向了,为节点的下一个节点,也就是首位连接起来了,也就形成也一个循环,同样的这也是,方便了查找;

链表的实现

刚刚我们了解到了链表的结构,那么现在我们就来实现它;首先,要实现一个链表,那么链表就是我们的对象了,所以我们先来看一下我们的对象有哪些属性方法:

a. 属性:节点(链表有节点组成),长度(也就是当前的节点数),

b. 方法:应该说链表的方法和之前的数组队列是比较相似的,首先,我们是要,得到我们的长度的方法,然后是添加节点的方法,删除节点的方法,更新节点的方法,当然这些方法都是根据自己的实际需要来定。

另外我们的节点中有数据域和引用域,并不那么单纯,所以我们也可以把节点看成一个对象,当然我们的节点就像就比较简单的了,只有数据和应用域这两个属性;

接下来的就比较简单了,我们先来看看单链表的实现:

单链表

首先是节点对象,因为单链表是一个引用域,所以我们只需要定义一个向下索引的引用域就好,然后是数据域,数据域,一般是一个数,但是也不是硬性规定,所以说对于数据域的定义来说,那就是随你咯。我们先来看一下代码:

因为定义的是private的类型,所以需要用到get和set方法;另外定义了两个构造方法,一个是实例化时,不带数据,另外一个是实例化的时候,就把数据给节点;

然后就是实现链表类了:部分代码如下:

其中的方法主要根据我们的需要来定;这里是定义了一个头节点,然后添加数据时添加在头节点的后面,所以,从头节点输出的话就是先进的后出了;

package 单链表;

/**
 * 自定义的单链表类
 *
 * @param <E>表示该类支持泛型
 */
public class MyLinkedlist<E> {

    private Node<E> root;// 申明一个头节点;
    private int size;// 声明单链表存储的节点数;
    /*
     * 在构造方法中实例化root;
     */

    public MyLinkedlist() {
        root = new Node<E>();// 实例化节点
    }

    /**
     * 获取链表中的元素;
     *
     * @param index
     *            链表节点所在的位置;
     */
    public E get(int index) {
        if (index > size || index <= 0)
            return null;
        Node<E> node = select(index);
        E e=node.getE();
        return e;

    }

    /**
     * 获取单链表中存储的元素总数
     *
     * @return 返回size属性
     */
    public int size() {
        return size;

    }

    /**
     * 获取指定索引位置的节点对象
     *
     * @param index索引位置
     * @return 返回获取到的节点对象
     */
    public Node<E> select(int index) {
        Node<E> node = root;
        /*
         * 从头节点开始获取他们的下一个节点;到当前节点为index-1;
         */
            for (int i = 0; i < index; i++) {
                node = node.getNext();
            }
        System.out.println("node:" + node);
        return node;

    }

    /**
     * 增加节点;向链表中添加元素
     * @param e 为要添加的元素
     */
    public void addnode(E e) {
        Node<E> nod = new Node<E>(e);// 实例化一个新的节点;
        Node<E> nextroot = root.getNext();// 获取root的下一个节点;
        nod.setNext(nextroot);// 把nod的下一个节点设为root的下一个节点
        root.setNext(nod);// 把root的下一个节点设为nod;
        size++;// 节点总数加1;

    }

    /**
     * 删除节点,删除链表中指定索引位置的元素
     * @param index要索引的节点的位置
     * @return 返回null为删除失败,否则删除成功
     */
    public E remove(int index) {
        /*
         * 当位置超过了size总数,或者小于等于0时,不执行操作,返回null;
         */
        if (index > size || index <= 0)
            return null;

        Node<E> nod = select(index - 1);// 获取删除节点的前一个节点;
        Node<E> nodt = nod.getNext();// 获取删除的节点;
        Node<E> not = nodt.getNext();// 获取要删除的后一个节点;
        nod.setNext(not);// 把要删除的后一个节点设为要删除节点的前一个节点的下一个节点;
        nodt.setNext(null);// 把要删除的节点的下一个节点置为null;
        size--;// 节点减少

        return nodt.getE();// 返回删除的节点的值;
    }

    /**
     * 根据元素,删除该元素所在的节点
     * @param e要删除的元素
     * @return 放回true删除成功
     */
    public boolean remove(E e) {
        Node<E> nods;
        System.out.println("size:" + size);
        for (int i = 1; i <= size; i++) {
            System.out.println("i:" + i);
            nods = select(i);
                System.out.println("nods" + nods);
                if (nods.getE() == e) {
                    Node<E> nod = select(i - 1);// 获取要删除节点的前一个节点;
                    Node<E> nodt = nods.getNext();// 获取要删除节点的后一个节点;
                    nod.setNext(nodt);// 把要把要删除的后一个节点设为要删除节点的前一个节点的下一个节点;
                    nods.setNext(null);// 把要删除的节点的下一个节点置为null;
                    size--;
                }
            }
        return true;
    }

    /**
     * 更新节点的数据;
     *
     * @param olde为要更新的数据
     * @param e为新的数据
     * @return 放回true则表示更新成功;
     */
    public boolean update(E olde, E e) {

        for (int i = 1; i <= size; i++) {
            Node<E> node = select(i);
            if (node.getE() == olde) {
                node.setE(e);
            }
        }
        return true;

    }

    /**
     * 更新节点的数据;
     *
     * @param index为要节点的位置;
     * @param e为新的数据
     * @return 放回true则表示更新成功;
     */
    public boolean update(int index, E e) {
        if (index > size || index <= 0)
            return false;
        Node<E> node = select(index);
        node.setE(e);
        return true;

    }

}

MyLinkedlist

package 单链表;

/**
 * 节点类;
 */
public class Node<E> {
    private E e;// 数据域;
    private Node<E> next;// 下一个节点;
    public Node() {//构造方法
    }
    public Node(E e) {//构造方法
        this.e = e;// 把数据传给当前数据域;
    }
    public E getE() {// 获取当前节点的数据域
        return e;
    }
    public void setE(E e) {// 设置当前节点的数据域;
        this.e = e;
    }
    public Node<E> getNext() {    // 得到当前的节点的下一个节点;
        return next;
    }
    // 设置当前节点的下一个节点;
    public void setNext(Node<E> next) {
        this.next = next;
    }
}

Node

双链表

简单来说,实现了单链表,那么双链表也就是好实现了,上面我们说了,双链表和单链表相比也就多了一个引用域,所以我们在写双链表的时候,也就是只要好好的考虑这一点,就可以了;实现步骤:

1.首先,我们同样是要定义两个类,节点类和链表类;

2.在类中实现对象的属性和方法,节点是一个数据域和两个引用域(一个向前,一个向后),链表中属性是一个头节点和一个尾节点,以及节点的长度,方法的话就有,得到size的方法,以及返回节点的值的方法,另外就是增加节点以及删除节点等对节点进行操作的方法了。与单链表相比,添加和删除节点的方法写起来比较繁琐写;

我们来看一下代码(删除节点的方法);

而单链表中可以说这里是比较简单地:

大概的就是这样啦;O(∩_∩)O。

package 双链表812;
public class DoubleNode<E> {
    private  DoubleNode<E>  next;//下一个节点
    private  DoubleNode<E>  front;//上一个节点;
    private  E e;//数据域;
    public DoubleNode<E> getNext() {
        return next;
    }
    public void setNext(DoubleNode<E> next) {
        this.next = next;
    }
    public DoubleNode<E> getFront() {
        return front;
    }
    public void setFront(DoubleNode<E> front) {
        this.front = front;
    }
    public E getE() {
        return e;
    }
    public void setE(E e) {
        this.e = e;
    }

    public  DoubleNode(E e){
        this.e=e;
    }
    public  DoubleNode(){

    }

}

DoubleNode

package 双链表812;

/**
 * 双链表;
 * @author YuanMo;
 * @param <E> 泛型;
 */
public class Mydoublelinkedlist<E> {
    private int size;//节点数;
    private  DoubleNode<E> root,trail;//头节点;尾节点
    //构造方法;
    public Mydoublelinkedlist(){
        root=new  DoubleNode<E>();//实例化root;
        trail=new  DoubleNode<E>();
        root.setNext(trail);//设置root的下一个节点为trail
        trail.setFront(root);//设置trail的下一个节点为root

    }

    /**
     * 得到链表中的节点数;
     * @return
     */
    public int getSize() {
        return size;
    }

    /**
     * 增加节点到链表中;
     * @param e为要添加的元素;
     */
    public void adddate(E e){
        DoubleNode<E> dnode=new DoubleNode<E>(e);
        DoubleNode<E> node=trail.getFront();//获取trail的上一个节点;
        dnode.setNext(trail);//把trail设为trail的下一个节点;
        trail.setFront(dnode);//把dnode设为trail的上一个节点;
        dnode.setFront(node);//把node设为dnode的上一个节点;
         node.setNext(dnode);//把dnode设为node的下一个节点;
        size++;

    }
    /**
     * 移除相应位置的节点;
     * @param index节点所在的位置;
     * @return 返回移除的元素表示取出成功;返回null表示移除失败;
     */
    public E remove(int index){
        if(index<=0||index>size)
        return null;
        DoubleNode<E> node=selectnext(index);//获取要删除的节点;
        DoubleNode<E> nodef=node.getFront();//获取要删除的节点的上一个节点;
        DoubleNode<E> noden=node.getNext();//获取要删除的节点下一个节点;
        nodef.setNext(noden);//把要删除的节点的上一个节点的下一个节点设为要删除的节点的下一个节点;
        noden.setFront(nodef);//把要删除的节点的下一个节点的上一个节点设为要删除的上一个节点;
        node.setFront(null);//把要删除的节点的前节点置为null;
        node.setNext(null);//把要删除的节点的前节点置为空;
        size--;
        return node.getE();

    }
    /**
     * 移除相应元素所在的节点
     * @param e 要删除的元素;
     * @return 放回true表示移除成功;
     */
    public boolean remove(E e){
        for(int i=1;i<=size;i++){
            DoubleNode<E> node=selectnext(i);
            if(node.getE()==e){
                DoubleNode<E> nodef=node.getFront();//获取要删除的节点的上一个节点;
                DoubleNode<E> noden=node.getNext();//获取要删除的节点下一个节点;
                nodef.setNext(noden);//把要删除的节点的上一个节点的下一个节点设为要删除的节点的下一个节点;
                noden.setFront(nodef);//把要删除的节点的下一个节点的上一个节点设为要删除的上一个节点;
                node.setFront(null);//把要删除的节点的前节点置为null;
                node.setNext(null);//把要删除的节点的前节点置为空;
                size--;
                break;//删除之后跳出循环;
            }
        }
        return true;
    }
    /**
     * 打印输出数据;
     */
    public void printdata(){
        for(int i=1;i<=this.getSize();i++){
            System.out.print(this.get(i)+" ");
        }

    }
    /**
     * 更新相应位置的节点的值;
     * @param index 节点的位置;
     * @param e 新的值
     * @return 放回更新后的值;
     */
    public  E updata(int index,E e){
        if(index<=0||index>size)
        return null;
        DoubleNode<E> node=selectnext(index);//获取当前位置的节点;
        node.setE(e);
        return node.getE();

    }

    /**
     * 更新节点中的值
     * @param olde 需要被替换掉的值
     * @param e  新的值
     * @return  放回true表示更新成功;否则失败
     */
    public  boolean updata(E olde,E e){
        for(int i=1;i<=size;i++){
            DoubleNode<E> node=selectnext(i);//获取当前位置的节点;
            if(node.getE()==olde){
                node.setE(e);
                break;
            }

        }
        return true;

    }

/**
 * 得到相应位置的值;
 * @param index 元素所在的位置;
 * @return 返回数值;
 */
    public E get(int index) {
        if(index>size||index<=0)
        return null;
        DoubleNode<E> node=selectnext(index);
        return node.getE();
    }
/**
 * 从前往后找相应位置的节点
 * @param index 元素所在的位置;
 * @return 返回相对赢得节点;
 */
    public DoubleNode<E> selectnext(int index) {
        DoubleNode<E> node = root;
        /*
         * 从头节点开始获取他们的下一个节点;到当前节点为index-1;
         */
            for (int i = 0; i < index; i++) {
                node = node.getNext();
            }
        return node;

    }
/**
 * 从后往前找到相应的节点;
 * @param index 元素所在的节点位置;
 * @return 返回相对赢得节点;
 */
    public DoubleNode<E> selectFront(int index) {
        DoubleNode<E> node = trail;
        /*
         * 从尾节点开始获取他们的下一个节点;到当前节点为index-1;
         */
            for (int i = 0; i < index; i++) {
                node =node.getFront();
            }
        return node;

    }

}

Mydoublelinkedlist

 

时间: 2024-12-11 12:36:03

java之链表的相关文章

java 单链表的实现

package liaobiao;//链表测试public class Node { private int value; private Node next; //存放下一个节点的指针 //构造方法,进行传参 public Node(int value){ this.value = value; } public Node(){ } //像链表的尾部加入元素,需要先找到最后一个节点 public void addNode(Node n ){ //需要先找到最后一个节点 Node node =t

Java 实现链表

链表相比数组操作更灵活,在空间效率方面比数组更有优势,虽然java中没有指针,但可以通过自定义类建立链表模型,进而实现链表. 分享下自己用java实现链表的过程: java代码: Node 类: package com.list.stack; /** * Setup Node class * @author gannyee * */ public class Node { //Declared element private Object element; //Declared next nod

Linked List Cycle leetcode java (链表检测环)

题目: Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space? 题解: 这道题连带着II是很经典的,在看CC150时候,纠结这个问题纠结了很久.在读了很多网上资料还有书的讲解以及和别人讨论之后,对这个专题终于明白了. 这一问只需要判断链表是否有环. 当链表没有环时是很好判断的,让一个指针一直往后走,遇见null了自然就没有环. 而如

java实现链表

今天和同学讨论时,他说java没有指针怎么实现链表.的确,在Java中没有指针.但是,Java中引用和C++中的引用有很大不同,而且具有一定指针的功能(过两天会总结).所以,就在家用Java实现了一下链表这种数据结构.目前我想到了两种方法用Java实现链表: 1.Java允许类的定义中出现该类对象,所以可以通过对该类对象的引用实现链表. 2.可以通过定义一个基类,通过子类的向上转型.通过父类指针模拟C++中的指针类型,从而实现链表. 废话不多说,上代码: 方法1 Node.java: packa

Java单链表、双端链表、有序链表实现

Java单链表.双端链表.有序链表实现 原创 2014年03月31日 23:45:35 标签: Java / 单链表 / 双端链表 / 有序链表 65040 单链表: insertFirst:在表头插入一个新的链接点,时间复杂度为O(1) deleteFirst:删除表头的链接点,时间复杂度为O(1) 有了这两个方法,就可以用单链表来实现一个栈了,见http://blog.csdn.net/a19881029/article/details/22579759 find:查找包含指定关键字的链接点

java单链表代码实现

用惯了C++,java写起来果然不太爽...不废话了,上代码... package javaInnerclassDemo; class Link{ class Node{ private String name; private Node next; public Node(String name){ this.name=name; } public void setname(String name){ this .name = name; } public String getname(){

(原创)用Java实现链表结构对象:单向无环链表

转载请注明本文出处:http://www.cnblogs.com/Starshot/p/6918569.html 链表的结构是由一个一个节点组成的,所谓链,就是每个节点的头尾连在一起.而单向链表就是:每个节点包含了当前节点的值和下一个节点引用.双向链表就是每个节点包含了当前节点的值和上下两个节点的引用.相对于数组结构,链表的增删效率会更加高. 这边文章主要讲怎么用Java实现一个简单的链表结构:单向无环链表.以及实现一些数据处理的方法. 首先,新建一个节点类(本次例子中的节点值都是字符串类型):

java对链表增删查改操作API

从c++方向搞点java副业.结果在静态链表这里绊了一跤.感谢巨人们的肩膀重见天日. 希望后来人少走些弯路. 废话少说,直接贴代码: 1.创建链表的节点类 public class Node { private Node node; private Object eleme; public void setEleme(Object eleme) { this.eleme = eleme; } public Node(){ this.eleme = null;node = null; } publ

JAVA实现链表面试题

这篇文章主要介绍了JAVA相关实现链表的面试题,代码实现非常详细,每一个方法讲解也很到位,特别适合参加Java面试的朋友阅读. 这份笔记整理了整整一个星期,每一行代码都是自己默写完成,并测试运行成功,同时也回顾了一下<剑指offer>这本书中和链表有关的讲解,希望对笔试和面试有所帮助. 本文包含链表的以下内容: 1.单链表的创建和遍历 2.求单链表中节点的个数 3.查找单链表中的倒数第k个结点(剑指offer,题15) 4.查找单链表中的中间结点 5.合并两个有序的单链表,合并之后的链表依然有

初学JAVA资料——链表

链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. 相比于线性表顺序结构,操作复杂.由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn