当前位置: 首页 > article >正文

数据结构-2.8.单链表的建立


一.尾插法建立单链表:取数据元素插入单链表表尾

1.图解:

对于时间复杂度,最好的时间复杂度是第一次,因为此时内层循环即找第i-1个结点就不执行了(不满足j<i-1),

内层循环和外层循环时间复杂度都是O(n),所以整个尾插操作的时间复杂度为O(n * n)。

(i为1时内层循环走0次,i为2时内层循环走1次,以此类推,i为n时内层循环走n-1次,那么一共走

0+1+2+...+(n-1)次,易知时间复杂度为O(n * n) )

但这个时间复杂度较高,因此没必要每次都从头开始寻找,可以设置一个指针指向表尾的最后一个数据结点,

然后当要在尾部插入一个新的数据元素时只需要对尾部结点进行后插操作即可:

后插后还需要把表尾指针向后移指向新的表尾数据结点:

2.代码演示:

#include<stdio.h>
#include<stdlib.h>
​
​
//定义单链表结点类型 
typedef struct LNode
{ 
    int data; //每个结点存放的数据元素 
    struct LNode *next; //指向下一个节点的指针,是链表型 
}LNode,*LinkList;
​
​
//初始化一个单链表(带头结点)
bool InitList(LinkList &L)
{
    //1.分配一个头结点
    L = (LNode*)malloc( sizeof(LNode) );
    //2.头结点判断
    if( L==NULL )
    {
        //代表头结点分配失败,比如内存不足 
        return false;
    }  
    /*3.走到这儿说明头结点分配成功
        由于第一个结点没存数据,所以第一个结点为NULL*/
    L->next = NULL;
    //4.分配成功
    return true;     
} 
​
​
//正向建立单链表
LinkList List_TailInsert(LinkList &L)
{
    //1.设置结点
    int x;
    /*2.建立头结点(头结点里的指针没必要设为NULL了,
                   因为之后必要加一个元素,头结点指向的元素一定不为空) */
    L = (LinkList)malloc( sizeof(LNode) );//初始化单链表 
    //3.设置表尾指针r
    LNode *r=L;
    LNode *s;
    //4.输入结点的值即要插入单链表的元素 
    scanf("%d",&x);
    //5.输入9999表示结束,9999不是固定的 
    while( x!=9999 )
    {
        s = (LNode *)malloc( sizeof(LNode) );
        s->data = x;
        r->next = s;
        //6.r指向新的表尾结点
        r=s;
        scanf("%d",&x); 
    } 
    //7.把尾结点指针置空
    r->next = NULL;
    return L; 
} 
​
​
int main()
{
    //1.声明一个指向单链表的指针
    LinkList L;
    //2.初始化一个空表
    InitList(L); 
    return 0;
}
该代码的图解:while循环就是插入操作核心

x为要插入单链表的元素,L为头结点(头结点里的指针没必要设为NULL了,因为之后必要加一个元素,头结点指向的元素一定不为空),*r代表表尾指针,一开始只有一个,表头即表尾:

假设x(x为要插入单链表的元素)为10,符合while循环条件,给要插入单链表的元素先分配一个空间,在再空间中存入元素,最后修改指针即r->next=s,此时表尾结点为s,则r=s:

注:r始终指向新的表尾结点。

之后以此类推,直到x不符合循环条件时停止插入,while循环结束(此时x为9999)后r->next=NULL即表尾后就是空的,代表单链表结束,最后返回新的单链表:

3.时间复杂度:如果插入n个结点则循环n次,所以时间复杂度为O(n)


二.头插法建立单链表:取数据元素插入单链表表头->可以使数据元素逆置

例如:

单链表表头插入11后为:

核心:相当于对头结点的后插操作即对指定结点的后插操作

1.图解:

2.代码演示:

#include<stdio.h>
#include<stdlib.h>
​
​
//定义单链表结点类型 
typedef struct LNode
{ 
    int data; //每个结点存放的数据元素 
    struct LNode *next; //指向下一个节点的指针,是链表型 
}LNode,*LinkList;
​
​
//初始化一个单链表(带头结点)
bool InitList(LinkList &L)
{
    //1.分配一个头结点
    L = (LNode*)malloc( sizeof(LNode) );
    //2.头结点判断
    if( L==NULL )
    {
        //代表头结点分配失败,比如内存不足 
        return false;
    }  
    /*3.走到这儿说明头结点分配成功
        由于第一个结点没存数据,所以第一个结点为NULL*/
    L->next = NULL;
    //4.分配成功
    return true;     
} 
​
​
//逆向建立单链表
LinkList List_HeadInsert(LinkList &L)
{
    LNode *s;
    //1.设置结点即要插入的元素 
    int x;
    //2.创建头结点
    L = (LinkList)malloc( sizeof(LNode) );
    //3.初始为空链表
    L->next = NULL;
    //4.输入结点的值
    scanf("%d",&x);
    //5.输入9999表示结束
    while( x!=9999)
    {
        s = (LNode *)malloc( sizeof(LNode) ); //创建新结点
        s->data = x;
        s->next = L->next;
        L->next = s; //将新结点插入表中,L为头指针
        scanf("%d",&x); 
    } 
    return L; 
} 
​
​
int main()
{
    //1.声明一个指向单链表的指针
    LinkList L;
    //2.初始化一个空表
    InitList(L); 
    return 0;
}
该代码的图解:while循环就是插入操作核心

1)x为要插入单链表的元素,先对单链表初始化即分配存储空间,再让p->next=NULL,初始为空链表:

注:

左部分代码中L->next=NULL不能省,如果省了,L->next(头结点指针)就有可能是一片神秘的未知区域,因为像这种

malloc动态分配申请的这片内存空间中可能有脏数据,如果不把L->next初始化,就不知道L->next是何物了,而且最后

实现插入后始终指向一片未知区域(每次插入都在头结点之后插,不影响尾结点):

2)while循环实现了后插操作,只不过每次执行后插操作的指定结点都是头结点

while循环中首先给要插入单链表的元素分配一个空间,在再空间中存入元素,再修改指针,

L->next一开始是秘:

根据题意,要让插入的元素即x指向秘,因此s->next = L->next :

最后把x接到头指针后面即可:

3.举例:

依次插入10,16,27,9999:

结果刚好和输入的顺序相反(因为每次插入都在头结点之后插),因此头插法建立单链表可以实现数据元素逆置

->对此,要想逆置一个单链表,可以依次取出该单链表的元素(用指针循环扫描依次取得元素),再利用头插法就可以实现

该单链表的原地逆置,也可以建立新链表把取出的元素利用头插法存入该新链表中;

也可以建立新链表,把要逆置的链表从后往前依次存入新链表实现逆置。


三.总结:



http://www.kler.cn/news/311656.html

相关文章:

  • 【Spring】IocDI详解(6)
  • VMWare17.5.2中Windows7企业版安装VMWareTools失败及解决办法
  • stm32单片机个人学习笔记3(GPIO输出)
  • Python 正则表达式详解:从基础匹配到高级应用
  • 华为OD机试 - 构成指定长度字符串的个数(Python/JS/C/C++ 2024 E卷 100分)
  • <<编码>> 第 14 章 反馈与触发器(7)--分频器与计数器 示例电路
  • 提升工作效率,引领编程新时代
  • 【大模型开发】 迎接AI新时代:Qwen2.5发布,超越LLaMA3!本地私有化部署:如何通过一键API调用不同模型?(附源码地址)
  • 速盾:cdn一般多长时间清理下缓存?
  • 基于Ubuntu22.04的cups安装与配置
  • Servlet的继承结构
  • Java语言程序设计基础篇_编程练习题**18.31 (替换单词)
  • 网络爬虫requests访问请求过程
  • java识别图片上的文字、java中语言库tessdate的使用
  • Web APIs 第二天
  • 如何应对pcdn技术中遇到的网络安全问题?
  • Docker 进入容器并运行命令的方法
  • iOS17找不到developer mode
  • 从黎巴嫩电子通信设备爆炸看如何防范网络电子袭击
  • Python 爬虫入门 - Request 静态页面数据获取
  • 支持升降压型、升压、降压、60V的1.2MHz频率LED恒流驱动器LGS63040、LGS63042
  • 记录可编辑表格(未完整)
  • 【25.3】C++智能交友系统
  • K8s1.28 部署Dashboard获取登录信息
  • STM32 HAL freertos零基础(八)事件标志组
  • 09 Shell Scriptfor循环结构语句
  • 防爆手机+鸿蒙系统,遨游通讯筑牢工业安全基石
  • Android实现自定义下拉列表绑定数据
  • WEB 编程:使用富文本编辑器 Quill 配合 WebBroker 后端
  • Go语言grequests库并发请求的实战案例