单链表的实现-JAVA

该内容为转载,原地址: 数据结构(一) 单链表的实现-JAVA

      数据结构还是很重要的,就算不是那种很牛逼的,但起码得知道基础的东西,这一系列就算是复习一下以前学过的数据结构和填补自己在这一块的知识的空缺。加油。珍惜校园中自由学习的时光。按照链表、栈、队列、排序、数组、树这种顺序来学习数据结构这门课程把。

                            -WH

一、单链表的概念

      链表是最基本的数据结构,其存储的你原理图如下图所示

          

      上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一个节点,就这样一节一节往下面记录,直到最后一个节点,其中的next指向null。

      链表有很多种,比如单链表,双链表等等。我们就对单链表进行学习,其他的懂了原理其实是一样的。

二、用java实现单链表

      语言只是一种工具,数据结构真正体会的是那种思想,这句话确实是这样,不管用什么写,其思想是不改变的。以前使用的是C++,现在用的是java,一步步来实现。

      2.1、编写一个Node类来充当结点的模型。我们知道,其中有两个属性,1存放数据的data,2存放下一结点的引用,

          

package com.wuhao.demo01;

public class Node {
    //为了方便,这两个变量都使用public,而不用private就不需要编写get、set方法了。
    //存放数据的变量,简单点,直接为int型
    public int data;
    //存放结点的变量,默认为null
    public Node next;

    //构造方法,在构造时就能够给data赋值
    public Node(int data){
        this.data = data;
    }
}

      2.2、单链表的简单操作(增加,删除,获取总长度,链表元素排序,链表遍历)  

            

         2.2.1、增加结点操作,addNode(Node)

             

           想法:    一开始也会想如果什么结点也没有。是不是需要判断插入的是第一个结点的问题,但写完后发现没有必要,是不是第一个结点操作都是一样的,所以通过移动的指针遍历整个链表,找到最后一个结点,往后添加即可。没难度。      

    /**
     * 增加操作
     *         直接在链表的最后插入新增的结点即可
     *         将原本最后一个结点的next指向新结点
     */
    public void addNode(Node node){
        //链表中有结点,遍历到最后一个结点
        Node temp = head;    //一个移动的指针(把头结点看做一个指向结点的指针)
        while(temp.next != null){    //遍历单链表,直到遍历到最后一个则跳出循环。
            temp = temp.next;        //往后移一个结点,指向下一个结点。
        }
        temp.next = node;    //temp为最后一个结点或者是头结点,将其next指向新结点
    }

         2.2.2、插入结点到链表的指定位置。 insertNodeByIndex(int index,Node node)

              

            注意:要知道插入操作需要的前提是什么,你才好写代码,写完之后,考虑如果在特殊位置上插入,是否也一样。还有需要进行插入位置是否可行的判断。

    /**
     * insertNodeByIndex:在链表的指定位置插入结点。
     *         插入操作需要知道1个结点即可,当前位置的前一个结点
     * index:插入链表的位置,从1开始
     * node:插入的结点
     */
    public void insertNodeByIndex(int index,Node node){
        //首先需要判断指定位置是否合法,
        if(index<1||index>length()+1){
            System.out.println("插入位置不合法。");
            return;
        }
        int length = 1;            //记录我们遍历到第几个结点了,也就是记录位置。
        Node temp = head;        //可移动的指针
        while(head.next != null){//遍历单链表
            if(index == length++){        //判断是否到达指定位置。
                //注意,我们的temp代表的是当前位置的前一个结点。
                //前一个结点        当前位置        后一个结点
                //temp            temp.next     temp.next.next
                //插入操作。
                node.next = temp.next;
                temp.next = node;
                return;
            }
            temp = temp.next;
        }
    }

         2.2.3、删除指定位置上的结点  delNodeByIndex(int index)

              

    /**
     * 通过index删除指定位置的结点,跟指定位置增加结点是一样的,先找到准确位置。然后进行删除操作。
     *             删除操作需要知道1个结点即可:和当前位置的前一个结点。
     * @param index:链表中的位置,从1开始
     *
     */
    public void delNodeByIndex(int index){
        //判断index是否合理
        if(index<1 || index>length()){
            System.out.println("给定的位置不合理");
            return;
        }

        //步骤跟insertNodeByIndex是一样的,只是操作不一样。
        int length=1;
        Node temp = head;
        while(temp.next != null){
            if(index == length++){
                //删除操作。
                temp.next = temp.next.next;
                return;
            }
            temp = temp.next;
        }
    }

          2.2.4、单链表进行选择排序  selectSortNode()  

                前提要知道什么是选择排序,如果不会,请查看我讲解排序的文章

              

              分析

              

    /**
     * 对链表中的结点进行排序,按照从小到大的顺序,使用选择排序。
     *         使用双层遍历。第一层遍历,正常遍历链表,第二层遍历,遍历第一层遍历时所用的结点后面所有结点并与之比较
     *         选择排序比较简单,明白其原理,就能够写的出来。
     */
    public void selectSortNode(){
        //判断链表长度大于2,不然只有一个元素,就不用排序了。
        if(length()<2){
            System.out.println("无需排序");
            return;
        }
        //选择排序
        Node temp = head;            //第一层遍历使用的移动指针,最处指向头结点,第一个结点用temp.next表示
        while(temp.next != null){    //第一层遍历链表,从第一个结点开始遍历
            Node secondTemp = temp.next;        //第二层遍历使用的移动指针,secondTemp指向第一个结点,我们需要用到是第二个结点开始,所以用secondNode.next
            while(secondTemp.next != null){//第二层遍历,从第二个结点开始遍历
                if( temp.next.data > secondTemp.next.data){    //第二层中的所有结点依次与第一次遍历中选定的结点进行比较,
                    int t = secondTemp.next.data;
                    secondTemp.next.data =  temp.next.data;
                    temp.next.data = t;
                }
                secondTemp = secondTemp.next;
            }
            temp = temp.next;
        }
    }

          2.2.5、单链表进行插入排序  insertSortNode()

              前提:要知道什么是插入排序。这个使用插入排序写了我好久,懵逼一样的状态,并且我认为我自己写效率不是很高。不管怎样,是骡子是马拿出来溜溜

              

              

    /**
     * 对链表进行插入排序,按从大到小的顺序,只要这里会写,那么手写用数组插入排序
     *    也是一样的。先要明白原理。什么是插入排序,这样才好写代码。
     *    插入排序:分两组,一组当成有序序列,一组当成无序,将无序组中的元素与有序组中的元素进行比较(如何比较,那么就要知道插入排序的原理是什么这里不过多阐述)
     *        这里我想到的方法是,构建一个空的链表当成有序序列,而原先的旧链表为无序序列,按照原理,一步步进行编码即可。
     *
     */
    public void insertSortNode(){
        //判断链表长度大于2,不然只有一个元素,就不用排序了。
        if(length()<2){
            System.out.println("无需排序");
            return;
        }
        //创建新链表
        Node newHead = new Node(0);    //新链表的头结点
        Node newTemp = newHead;        //新链表的移动指针
        Node temp = head;        //旧链表的移动指针
        if(newTemp.next == null){        //将第一个结点直接放入新链表中。
            Node node = new Node(temp.next.data);
            newTemp.next = node;
            temp = temp.next;    //旧链表中指针移到下一位(第二个结点处)。
        }
        while(temp.next != null){     //    遍历现有链表
            while(newTemp.next != null){
                //先跟新链表中的第一个结点进行比较,如果符合条件则添加到新链表,注意是在第一个位置上增加结点
                //如果不符合,则跟新链表中第二个结点进行比较,如果都不符合,跳出while,判断是否是到了新链表的最后一个结点,如果是则直接在新链表后面添加即可

                if(newTemp.next.data < temp.next.data){
                    Node node = new Node(temp.next.data);
                    node.next = newTemp.next;
                    newTemp.next = node;
                    break;
                }
                newTemp = newTemp.next;
            }
            if(newTemp.next == null){//到达最末尾还没符合,那么说明该值是新链表中最小的数,直接添加即可到链表中即可
                //直接在新链表后面添加
                Node node = new Node(temp.next.data);
                newTemp.next = node;
            }
            //旧链表指针指向下一位结点,继续重复和新链表中的结点进行比较。
            temp = temp.next;
            //新链表中的移动指针需要复位,指向头结点
            newTemp = newHead;
        }
        //开始使用新链表,旧链表等待垃圾回收机制将其收回。
        head = newHead;

    }

    

          2.2.6、当然还可以使用冒泡排序、归并排序,等等等,都可以自己去尝试,我就不写了。如果不懂这些排序,那么就看我写排序的文章把。

          2.2.7、计算单链表的长度

              

    /**
     * 计算单链表的长度,也就是有多少个结点
     * @return    结点个数
     */
    public int length() {
        int length=0;
        Node temp = head;
        while(temp.next != null){
            length++;
            temp = temp.next;
        }
        return length;
    }

          2.2.8、遍历单链表,打印data

                

 

    /**
     * 遍历单链表,打印所有data
     */
    public void print(){
        Node temp = head.next;
        while(temp != null){
            System.out.print(temp.data+",");
            temp = temp.next;
        }
        System.out.println();
    }

  

三、总结

    基本的单链表操作就是上面这些了,自己完全手动写一写,会对单链表这种数据结构的理解有很大的帮助。当然其中比较难的是在于对链表的排序上,说难也不难,只要懂的几种排序的原理,就跟写伪代码一样,去实现即可。这里还有一些操作,大家可以动手做一做,我会在下一篇文章中讲解这些答案。

    3.1、如何从链表中删除重复数据

    3.2、如何找出单链表中的倒数第k个元素

    3.3、如何实现链表的反转

    3.4、如何从尾到头输出单链表

    3.5、如何寻找单链表的中间结点

    3.6、如何检测一个链表是否有环

    3.7、如何在不知道头结点的情况下删除指定结点

    3.8、如何判断两个链表是否相交

原文地址:https://www.cnblogs.com/winner521/p/8759022.html

时间: 2024-10-27 07:58:04

单链表的实现-JAVA的相关文章

Singly Link List(单链表的实现java)

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

数据结构(一) 单链表的实现-JAVA

数据结构还是很重要的,就算不是那种很牛逼的,但起码得知道基础的东西,这一系列就算是复习一下以前学过的数据结构和填补自己在这一块的知识的空缺.加油.珍惜校园中自由学习的时光.按照链表.栈.队列.排序.数组.树这种顺序来学习数据结构这门课程把. -WH 一.单链表的概念 链表是最基本的数据结构,其存储的你原理图如下图所示 上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一

单链表逆置Java

package com.kpp; /** * 单链表逆置 * 将单链表从第一个结点和第二个节点之间断开,然后将第2,3...个结点依次插入第一个结点之前 * @author kpp * */ class LNode{ private String data; private LNode next; } public class LinkedListReverse { private static void reverse(LNode head){ if(head == null||head.ne

【转】单向链表(单链表)的Java实现

最近被问到链表,是一个朋友和我讨论Java的时候说的.说实话,我学习编程的近一年时间里,学到的东西还是挺少的.语言是学了Java和C#,关 于Web的学了一点Html+css+javascript.因为比较偏好,学习WinForm时比较认真,数据库操作也自己有所研究.但链表这个东西我 还真没有学习和研究过,加上最近自己在看WPF,而课程也到了JSP了,比较紧. 但是我还是抽了一个晚上加半天的时间看了一下单向链表.并且使用Java试着写了一个实例出来.没有接触过链表的朋友可以作为参考,希望大家多提

java数据结构:单链表常见操作代码实现

一.概述: 本文主要总结单链表常见操作的实现,包括链表结点添加.删除:链表正向遍历和反向遍历.链表排序.判断链表是否有环.是否相交.获取某一结点等. 二.概念: 链表: 一种重要的数据结构,HashMap等集合的底层结构都是链表结构.链表以结点作为存储单元,这些存储单元可以是不连续的.每个结点由两部分组成:存储的数值+前序结点和后序结点的指针.即有前序结点的指针又有后序结点的指针的链表称为双向链表,只包含后续指针的链表为单链表,本文总结的均为单链表的操作. 单链表结构: Java中单链表采用No

线性表—单链表

.1.链式存储结构实现 单链表和双链表(这边讲单链表). 2.基础概念 a.结点:结点由数据域和地址域(链)两部分组成.而结点整体在效果上可以看作是该结点的地址(指针).这个地址域一般是后继元素的地址(即下一个结点的总体).所以最后一个元素的地址域为^,其表示空,即没有后续元素.b.单链表:每个结点只有一个地址域的线性链表称为单链表.c.双链表:每个结点有两个地址域的线性表链称为双链表,两个地址域分别指向前驱元素和后继元素. 3.单链表的实现 线性表接口LList: package com.cl

【算法导论学习-23】两个单链表(single linked)求交点

问题:A.B两个单链表如果有交点,返回第一个交点在A中的位置(链表头结点位置为0). 分析:A.B如果有交点,交点的后继一定也是交点,所以一定是Y型相交,所以算法的思想如下 1)  求得A.B的长度,比如ALength,Blength 2)  判断ALength,Blength谁大,比如Alength>Blength 3)  Alength移动到Alength-Blength的位置,开始判断每个节点是否相等,相等则退出. 以本博客中"[算法导论学习-20]单链表(single linked

数据结构----顺序表与单链表(JAVA)

下面为学习顺序表和单链表的一些基本操作函数: 1 public class SeqList<T> extends Object { 2 protected int n; 3 protected Object[] element; 4 5 public SeqList(int length) { 6 this.element = new Object[length]; 7 this.n = 0; 8 } 9 10 public SeqList() { 11 this(64); 12 } 13 1

数据结构复习--java实现单链表基本操作

单链表的基本操作包括建立单链表.查找运算(按序查找和按值查找).插入运算(前插和后插)和删除运算.下面给出具体的java实现程序: package com.zpp.test; //首先创建一个节点类 public class Node { private Node next; //指针域 private int data;//数据域 public Node( int data) { this. data = data; } } package com.zpp.test; public class