zoukankan      html  css  js  c++  java
  • 9.8线性表之单链表

    9.8线性表之单链表

    链表的概念

    链表,别名:链式存储结构

    链表的特点:

    • 不限制数据的物理存储状态

      • 存储的数据物理位置是随机的不是连续的

    • 每个数据存储时都配备一个指针,用于指向自己的直接后继元素--->前驱和后继

    使用链表存储数据{1,2,3}图示:

    链式存储结构

    数据元素随机存储,并通过指针表示数据之间逻辑关系的存储结构就是链式存储结构

    链表的组成部分

    • 数据元素本身,数据域

    • 指向直接后继元素的指针,指针域

    链表中元素存储结构示意图:

    特点:

    • 上诉结构在链表中称为节点。链表实际存储的是一个一个的节点,真正的数据元素包含在这些节点中

    节点存储结构图示:--->简单结构

    C语言实现节点的结构体

    typedef struct Link{
       char element; //数据域
       struct Link * next; //指针域,指向直接后继元素
    }link;
    /*
    link为节点名,每个节点都是一个 link 结构体
    类似宏,一个link就包含数据域和指针域,指针域是一个指针变量
    */

    Go实现:

    /*
    创建链表的节点结构体:
    1、数据域
    2、指针域--->一个指针变量,属于该结构体的指针变量
    */
    type Link struct {
    /*创建数据域*/
    element int
    /*创建指针域--->一个指针变量,属于该结构体*/
    *Link
    }

    由于指针域中的指针要指向的也是一个节点,因此要声明为 Link 类型(这里要写成 struct Link* 的形式)

    头节点、头指针、首元节点

    一个完整的链表由以下几个部分构成:

    • 头指针:一个普通的指针。永远指向链表第一个节点的位置。用于指明链表的位置,便于后期找到链表并使用表中的数据

    • 节点:

      • 头节点:不存任何数据的空节点,通常作为链表的第一个节点--->头节点是必须的。方便解决某些实际问题

      • 首元节点:链表中称第一个存有数据的节点为首元节点--->只是一个称谓,没有实际意义

      • 其他节点:链表中其他的节点

    链表中有头节点时,头指针指向头节点;反之,若链表中没有头节点,则头指针指向首元节点。

    完整链表的结构图示:

    链表的创建

    创建一个链表需要做的事情:

    • 声明一个头指针

    • 声明一个头节点

    • 创建多个存储数据的节点

    创建一个存储 {1,2,3,4} 且无头节点的链表示例代码:--->要结合上面的结构体来看

    //初始化link结构体
    link * initLink(){
       link * p = NULL; //创建一个头指针--->该指针式link结构体的一个实例。包含了数据域和指针域
       link * temp = (link*) malloc(sizeof(link)); //创建首元节点--->第一个拥有数据的节点--->也是一个link结构体的实例
       //首元节点初始化--->获取结构体成员
       temp->elem = 1;
       temp->next = NULL;
       //使头指针指向首元节点
       p = temp;
       
       //从第二个节点开始创建节点
       for(int i=2;i<5;i++){
           //创建一个新节点并且初始化
           link *a = (link*)malloc(sizeof(link));
           //初始化数据域与指针域
           a->elem = i;
           a->next = NULL;
           //将上诉的首元节点与新节点建立逻辑关系
           temp->next = a; //next是结构体的一个link结构体指针,a本身就是一个结构体
           //指针temp每次都指向新链表的最后一个节点,其实就是 a节点,写temp=a也对
           temp = temp->next;
      }
       //返回建立的节点,只返回头指针p即可。通过头指针找到整个链表
       return p;
    }

    创建一个含头节点的链表示例代码:

    link * initLink(){
       link * p = NULL; //这是一个头指针
       link * f = (link*)malloc(sizeof(link)); //这是一个头节点
       p = f; //这是让头指针指向头节点--->赋值操作
       
       //开始创建其他节点
       for(int i=1;i<5;i++){
           //创建其他节点
           link * a=(link)malloc(sizeof(link));
           //初始化数据域和指针域
           a->elem = i; //这是数据域
           a->next = NULL; //这是指针域
           //让头节点与首元节点发生逻辑联系--->用头指针的指针域指向首元节点
           f->next=a;
           //指针每次都指向新链表的最后一个节点
           f=f->next //其实就是f=a->next
      }
       //返回头指针
       return p;
    }

    调用 initLink 函数,创建一个存储 {1,2,3,4} 的链表示例代码:

    #include <stdio.h>
    #include <stdlib.h>

    //创建节点结构体--->一个节点应该包含的成员
    typedef struct Link{
       /*数据域*/
       int element;
       /*指针域*/
       struct Link *next; //一个指针变量,属于结构体的指针变量
    }link;

    //初始化链表函数
    link * initLink();

    //定义初始化方法
    link * initLink(){
       /*创建头指针*/
       link * f = NULL;
       /*创建首元节点*/
       link * temp = (link*)malloc(sizeof(link));
       //初始化首元节点
       temp->elem=1;
       temp->next=NULL;
       
       //循环创建其他节点
       for(int i=2;i<5;i++){
           //创建其他节点
           link * a=(link*)malloc(sizeof(link));
           //初始化其他节点数据
           a->elem=i;
           a->next=NULL;
           
           //让首元节点与其他节点发生逻辑联系--->首元节点的指针域指向下一个节点的数据域
           temp->next = a;
           //首元节点的数据域指向下一个节点的数据域
           temp=temp->next;
      }
       //返回头指针
       return p;
    }

    //输出链表函数--->指针数据
    void display(link *p);

    //定义输出方法
    void display(link *p){
       //将temp指向头节点
       link * temp = p;
       //只要temp指针指向的结点的next不是Null,就执行输出语句
       while(temp){
           printf("%d", temp->elem);
           temp = temp->next; //指向下一个节点指针域
      }
       printf("\n")
    }

    如果使用带有头节点创建链表的方式,则输出链表的 display 函数需要做适当地修改:--->交换输出和指向的顺序,先指向在输出

    void display(link *p){
       //将temp指向头节点
       link * temp = p;
       //只要temp指针指向的结点的next不是Null,就执行输出语句
       while(temp){
           temp = temp->next; //指向下一个节点指针域
           printf("%d", temp->elem);
      }
       printf("\n")
    }

     

  • 相关阅读:
    The .NET weak event pattern in C#
    Setting an Event to Null
    Android: INSTALL_FAILED_UPDATE_INCOMPATIBLE错误解决措施
    快速打开 Mac OS X 隐藏的用户资源库文件夹
    Complete uninstall on Mac, HELP!
    为什么MacBook装Windows这么火?
    mac 刻录ISO系统盘
    MySQL子查询慢现象的解决
    程序人生的四个象限和两条主线
    Xamarin.Android,Xamarin.iOS, Linking
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/15244313.html
Copyright © 2011-2022 走看看