链式存储结构之单链表

1.线性表的链式存储结构

线性表的链式存储结构允许数据元素存在任意未被占用的内存空间,因为在线性表的链式存储结构中,除了存储数据元素相关的数据信息之外,还存储了数据元素的后继元素存储地址,这样通过当前数据元素很容易找到下一个数据元素。

链式存储结构中,存取一个数据元素内容信息和直接后继的存储位置的结构称为结点,存储数据元素内容信息的域称为数据域,存储直接后继存储位置的域称为指针域。n个结点链接成一个链表,每个结点中只包含一个指针域的称为单链表。

2.单链表

2.1 结点

代码实现单链表,首先需要创建结点。我们知道结点中存储的是一个数据元素的数据信息和直接后继的内存地址(也就是下一个结点的内存地址),因此,可使用如下代码实现结点的创建。

class Node{
    int data;
    Node next;
    //直接使用数据信息初始化结点
    public Node(int data){
        this.data=data;
    }
    @Override
    public String toString() {
        return "Node [data=" + data + ", next=" + next + "]";
    }
}

实例化一个结点Node node=new Node(0); node.next指向的是后继结点,还是Node类型。

2.2 单链表的创建

在对单链表进行操作之前,比如存储,读取,插入,删除等,首先需要创建单链表。

当node的next指向的下一个元素不为null时,一直遍历,知道找到最后一个结点,即node.next=null的node,将创建的新结点添加到链表中。

代码实现:

//创建单链表
public static Node singleList(){
    Node head=node0;
    add(new Node(2));
    add(new Node(1));
    add(new Node(5));
    add(new Node(3));
    add(new Node(7));
    add(new Node(6));
    add(new Node(9));
    add(new Node(1));
    add(new Node(8));
    return head;
}

//向单链表中添加元素
public static void add(Node newNode){
    Node node=node0;
    while(node.next!=null){
        node=node.next;
    }
    node.next=newNode;
}

2.3 读取单链表的第i个数据元素

算法思路:
    1. 判断i是否合法,即i是否在链表的长度范围内;
    2. 声明一个指针temp指向链表的第一个结点,初始化j从1开始;
    3. 当j<i时,让temp指针向后移动,不断指向下一个结点,j累加1;
    4. 若查找成功,返回结点temp的数据。

代码实现:

//读取单链表的第i个数据
public static int findNode(int i){
    int iData=0;
    int length=calculateLength();
    System.out.println("length:"+length);
    if(i>length || i<1){
        System.out.println("i无效");
    }else{
        int j=1;
        while(j<i){
            temp=temp.next;
            j=j+1;
        }
        iData=temp.data;
    }
    return iData;
}

//计算单链表的长度
public static int calculateLength(){
    //temp1指向链表的第一个结点
    Node temp1=temp;
    int length=0;
    //计算单链表的长度
    //头结点放在第一元素之前,所以头结点不属于链表的长度计算范围
    while(temp1!=null){
        length=length+1;
        temp1=temp1.next;
    }
    return length;
}

读取算法的时间复杂度分析:该算法的时间复杂度取决于i的位置,当i为1时,不需要遍历,第一个就取出来了,当i为n时,则需遍历n-1次,因此最坏时间复杂度是O(n)。

2.4 单链表的第i个位置插入结点

算法思路:
    1. 声明一个指针temp2指向链表头结点,初始化j从1开始;
    2. 当j<i时,遍历链表,让temp2的指针向后移,指向下一个结点,且j累加1;
    3. 若到链表末尾,则说明第i个结点不存在;
    4. 否则查找成功,执行单链表的插入标准语句:node.next=temp.next; temp.next=node;

代码实现:

public static void insert(Node node,int i){
    Node temp2=temp;
    System.out.println(temp2);
    int j=1;
    while(j<i){
        temp2=temp2.next;
        j=j+1;
    }
    if(j>i){
        System.out.println("i超出线性表长度");
    }
    node.next=temp.next;
    temp.next=node;
}
    

2.5 单链表的第i个位置删除结点

算法思路:
    1. 声明一个指针temp2指向链表头结点,初始化j从1开始;
    2. 当j<i时,遍历链表,让temp2的指针向后移,指向下一个结点,且j累加1;
    3. 若到链表末尾,则说明第i个结点不存在;
    4. 否则查找成功,执行单链表的插入标准语句:node.next=node.next.next;

代码实现:

public static void delete(int i){
    Node temp3=temp;
    System.out.println(temp3);
    int j=1;
    while(j<i){
        temp=temp3.next;
        j=j+1;
    }
    if(j>i){
        System.out.println("删除位置不存在!");
    }
    temp3.next=temp3.next.next;
}

单链表插入和删除的算法时间复杂度分析:由上面的插入和删除操作,可以简单地将插入和删除操作分为两个步骤实现,第一步首先遍历i个结点,第二步就是在i位置插入或删除结点。可以看出算法的时间复杂度为O(n)。

之前分析过顺序存储结构的插入和删除算法时间复杂度为O(n),所以单链表在插入和删除操作上,与顺序存储结构的插入和删除是没有多大区别的。但是我们要在i的位置插入10个结点,对于顺序存储结构,每次都需要移动n-i个结点,每次都是O(n),而对于单链表,只需在第一次遍历得到i的指针,时间复杂度为O(n),之后的插入直接赋值指针即可实现,时间复杂度都是O(1)。所以单链表对于多个结点的插入和删除操作是很高效的。

完整的代码:

package com.java.ListInsert;
public class SingleList {
    static Node node0=new Node(0);
    //初始化temp指针指向第一个结点
    static Node temp=singleList().next;
    public static void main(String[] args){
        delete(1);
        int r=findNode(3);
        System.out.println(r);
    }

    //单链表的删除
    public static void delete(int i){
        Node temp3=temp;
        System.out.println(temp3);
        int j=1;
        while(j<i){
            temp=temp3.next;
            j=j+1;
        }
        if(j>i){
            System.out.println("删除位置不存在!");
        }
        temp3.next=temp3.next.next;
    }
    //单链表的插入
    public static void insert(Node node,int i){
        Node temp2=temp;
        System.out.println(temp2);
        int j=1;
        while(j<i){
            temp2=temp2.next;
            j=j+1;
        }
        if(j>i){
            System.out.println("i超出线性表长度");
        }
        node.next=temp.next;
        temp.next=node;
    }

    //读取单链表的第i个数据
    public static int findNode(int i){
        int iData=0;
        int length=calculateLength();
        System.out.println("length:"+length);
        if(i>length || i<1){
            System.out.println("i无效");
        }else{
            int j=1;
            while(j<i){
                temp=temp.next;
                j=j+1;
            }
            iData=temp.data;
        }
        return iData;
    }

    //计算单链表的长度
    public static int calculateLength(){
        //temp1指向链表的第一个结点
        Node temp1=temp;
        int length=0;
        //计算单链表的长度
        //头结点放在第一元素之前,所以头结点不属于链表的长度计算范围
        while(temp1!=null){
            length=length+1;
            temp1=temp1.next;
        }
        return length;
    }

    //创建单链表
    public static Node singleList(){
        Node head=node0;
        add(new Node(2));
        add(new Node(1));
        add(new Node(5));
        add(new Node(3));
        add(new Node(7));
        add(new Node(6));
        add(new Node(9));
        add(new Node(1));
        add(new Node(8));
        return head;
    }

    //向单链表中添加元素
    public static void add(Node newNode){
        Node node=node0;
        while(node.next!=null){
            node=node.next;
        }
        node.next=newNode;
    }

}
class Node{
    int data;
    Node next;
    //直接使用数据信息初始化结点
    public Node(int data){
        this.data=data;
    }
    @Override
    public String toString() {
        return "Node [data=" + data + ", next=" + next + "]";
    }
}

原文地址:https://www.cnblogs.com/naihuangbao/p/10262351.html

时间: 2024-08-25 04:33:32

链式存储结构之单链表的相关文章

数据结构之线性表——链式存储结构之单链表(php代码实现)

<?php /**  *  * 1. 类LNode用作创建单链表时,生成新的节点.  * 2. 类SingleLinkList用于创建单链表以及对单链表的一些操作方法(实例化此类就相当于创建了一个空链表)  * 3. CreateListHead: 具有$num个数据元素的单链表的创建--头插法  * 4. CreateListTail: 具有$num个数据元素的单链表的创建--尾插法  * 5. DestroyList: 销毁单链表  * 6. ClearList:清空单链表  * 7. Li

二叉树的链式存储结构----二叉链表

头文件:head.h #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof()

链式存储结构之静态链表

1.静态链表 用数组代替指针来描述链表叫做静态链表.静态链表是为了给没有指针的高级语言设计的一种实现单链表能力的方法.首先让数组的元素都由两个数据域组成,data和cur,即数组的每一个下标都对应一个data和一个cur. 2.静态链表的初始化静态链表的初始化如下图: 初始化静态链表的代码实现: public static void initList(){ ArrayData[] array=new ArrayData[maxSize]; for(int i=0;i<maxSize-1;i++)

数据结构开发(5):线性表的链式存储结构

0.目录 1.线性表的链式存储结构 2.单链表的具体实现 3.顺序表和单链表的对比分析 4.小结 1.线性表的链式存储结构 顺序存储结构线性表的最大问题是: 插入和删除需要移动大量的元素!如何解决? 链式存储的定义: 为了表示每个数据元素与其直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息. 链式存储逻辑结构: 基于链式存储结构的线性表中,每个结点都包含数据域和指针域 数据域:存储数据元素本身 指针域:存储相邻结点的地址 专业术语的统一: 顺序表 基于顺序存储

二叉树的链式存储结构--二叉链表

1 二叉树的链式存储结构 //二叉链表的结点结构定义 typedef struct BiTNode { int data; struct BiTNode *lchild; struct BiTNode *rchild; }BiTNode; typedef struct BiTNode *BiTree; 结构示意图如下: 2 二叉树的遍历方法 (1)前序遍历:先访问根结,然后前序遍历左子树,再前序遍历右子树. (2)

03.线性表(二)链式存储结构.单链表1

链式存储结构.单链表1 1.基本概念 为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置) (1)数据域:存储线性表数据元素数据信息的域称为数据域: (2)指针域:把存储直接后继位置(下一个数据元素的地址)的域称为指针域,指针域中存储的信息为指针或链: (3)结点(Node):由数据域和指针域两部分信息组成数据元素ai的存储映像,称为结点. (4)头指针:把链表中第一个结点的存储

04.线性表(三)链式存储结构.单链表2

链式存储结构.单链表2 顺序存储结构的创建实质是一个数组的初始化,存储空间连续且其大小和类型已经固定:单链表存储空间不连续,是一种动态结构且它所占用空间的大小和位置是不需要预先分配划定的,可以根据系统的情况和实际的需求即时生成. 一.单链表的整表创建 创建单链表的过程就是一个动态生成链表的过程,即从"空表"的初始化起,依次建立各元素结点,并逐个插入链表. 1.算法思路 (1)声明一个结点p和计数器变量i; (2)初始化一空链表L (3)让链表L的头结点的指针指向NULL,即建立一个带头

05.线性表(四)链式存储结构.静态链表

链式存储结构.静态链表   一.静态链表 1.静态链表存储结构 单链表是通过指针实现的,但是我们也可以通过数组来代替指针描述单链表,即静态链表.如何实现静态链表?构造数组的元素由两个数据域组成:data和cur,即数组的每个下标都对应一个data和一个cur. 数据域data:用来存放数据元素,即要处理的数据: 游标cur:存放该元素的后继在数组中的下标,相当于单链表中的next指针: 为了方便插入数据,我们通常会把数组建立得大一些,以便有一些空闲空间而不致于出现溢出情况. 线性表的静态链表存储

线性表的链式存储结构(链表)

链表:基于来链式存储的线性表 链式逻辑存储结构:基于链式存储结构的线性表中,每个节点都包含数据域和指针域(数据域:存储数据元素本身.指针域:存储相邻节点的地址.) 单链表:链表的每个节点只包含后一个元素的地址信息  循环链表:链表的最后一个元素的包含第一个元素的地址信息 双向链表:链表的节点中包含后驱和前驱的地址信息 链表基本概念: 头节点(辅助节点.不包含数据域,指针域指向第0个数据元素)+ 数据节点(数据域+地址域)+  尾节点(指针域为空或某一值,只有数据域) 单链表节点定义: struc