【408篇】C语言笔记-第十章(线性表)

news2024/9/21 10:40:11

文章目录

    • 第一节:线性表的顺序表示
      • 线性表
        • 1. 定义
        • 2. 特点
      • 线性表的顺序表示
        • 1. 顺序表
        • 2. 优缺点比较
        • 3. 插入操作
        • 4. 删除操作
        • 5. 动态分配
      • 代码示例
    • 第二节:线性表的链式表示
      • 单链表
      • 优缺点对比
      • 插入操作
      • 删除操作
      • 代码示例

第一节:线性表的顺序表示

线性表

1. 定义

由n(n>=0)个相同类型的元素组成的有序集合。

L=(a1,a2,……,ai-1,ai,ai+1,……,an)

  • 线性表中元素个数n,称为线性表的长度。当n=0时,为空表。
  • a1是唯一的“第一个”数据元素,an是唯一的“最后一个”数据元素。
  • ai-1为ai的直接前驱,ai+1为ai的直接后继

2. 特点

  • 表中元素的个数是有限的。
  • 表中元素的数据类型都相同。意味着每一个元素占用相同大小的空间。
  • 表中元素具有逻辑上的顺序性,在序列中各元素排序有其先后顺序。

线性表的顺序表示

1. 顺序表

逻辑上相邻的两个元素在物理位置上也相邻。

顺序表的定义:

#define MaxSize 50  // 定义线性表的长度
typedef struct{
    ElemType data[MaxSize]; // 顺序表的元素
    int len;   // 顺序表的当前长度
}SqList;  // 顺序表的类型定义

2. 优缺点比较

3. 插入操作

分析

最好情况:在表尾插入元素,不需要移动元素,时间复杂度为O(1)。

最坏情况:在表头插入元素,所有元素依次后移,时间复杂度为O(n)。

平均情况:在插入位置概率均等的情况下,平均移动元素的次数为n/2,时间复杂度为O(n)。

代码片段

// 判断插入位置i是否合法(满足1<=i<=len+1)
// 判断存储空间是否已满(即插入X后是否会超出数组长度)
for(int j=L.len;j>=i;j--){
    L.data[j]=L.data[j-1]; // 将最后一个元素到第i个元素依次后移一位
}
L.data[i-1]=x;  // 空出的位置i除放入x
L.len++;  // 线性表长度加1

说明:我们在实际的操作中下标是从0开始的,但是说的第几个元素时从1开始的。第i个元素,下标实际为i-1。

4. 删除操作

分析

最好情况:删除表尾元素,不需要移动任何元素,时间复杂度为O(1)。

最坏情况:删除表头元素,之后的所有元素依次前移,时间复杂度为O(n)。

平均情况:在删除位置概率均等的情况下,平均移动元素的次数为(n-1)/2,时间复杂度为O(n)。

代码片段

// 判断删除位置i是否合法(满足1<=i<=len)
e=L.data[i-1];  // 将被删除的元素赋值给e
for(int j=i;j<L.len;j++){
    L.data[j-1]=L.data[j];  // 将删除位置后的元素依次前移
}
L.len--;  // 线性表长度减1

说明:我们在实际的操作中下标是从0开始的,但是说的第几个元素时从1开始的。第i个元素,下标实际为i-1。

5. 动态分配

#define InitSize 100  // 表长度的初始定义
typedef struct{
    ElemType *data;  // 指示动态分配数组的指针
    int MaxSize,length;  // 数组的最大容量和当前个数
}SeqList;  // 动态分配数组顺序表的类型定义

C的初始动态分配语句为:

L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);

C++的初始动态分配语句为:

L.data=new ElemType[InitSize];

代码示例

#include <stdio.h>

#define MaxSize 50
typedef int ElemType;
// 静态分配
typedef struct {
    ElemType data[MaxSize];
    int len;  // 当前顺序表中元素个数
}SqList;

// 插入
// i表示插入的位置,从1开始,e要插入的元素
bool ListInsert(SqList &L,int i,ElemType e){
    if(i<1 || i>L.len+1){  // 判断插入位置是否合法
        return false;
    }
    if(L.len>=MaxSize){  // 判断存储空间是否已满
        return false;
    }
    for(int j=L.len;j>=i;j--){ // 移动顺序表中的元素
        L.data[j]=L.data[j-1];
    }
    L.data[i-1]=e;
    L.len+=1; // 添加一个元素,顺序表元素加1
    return true;
}

// 删除
// i表示删除的位置,从1开始。使用元素e的引用的目的是拿出对应的值
bool ListDel(SqList &L,int i,ElemType &e){
    if(i<1 || i>L.len){ // 判断删除的位置是否合法
        return false;
    }
    e=L.data[i-1]; // 获取顺序表中对应的元素,赋值给e
    for (int j=i;j<L.len;j++) {
        L.data[j-1]=L.data[j];
    }
    L.len-=1; // 删除一个元素,顺序表长度减1
    return true;
}

// 查找
// 查找成功,返回位置,位置从1开始,查找失败,返回0。e表示要查找的元素,这里不考虑重复元素
int ListFind(SqList L,ElemType e){
    for(int i=0;i<L.len;i++){
        if(L.data[i]==e){
            return i+1;  // 加1就是元素在顺序表中的位置
        }
    }
    return 0;
}

// 修改
// i表示修改的位置,e表示修改后的值
bool ListUpdate(SqList &L,int i,ElemType e){
    if(i<1 || i>L.len){ // 判断修改的位置是否合法
        return false;
    }
    L.data[i-1]=e;
    return true;
}

// 打印线性表
void PrintList(SqList L){
    for(int i=0;i<L.len;i++){
        printf("%3d",L.data[i]);
    }
    printf("\n");
}
int main() {
    printf("init Linear table\n");
    SqList L; // 顺序表的名称
    bool ret;
    L.data[0]=1;
    L.data[1]=2;
    L.data[2]=3;
    L.len=3;  // 总计3个元素
    printf("insert Linear table element\n");
    ret=ListInsert(L,2,50);
    if(ret){
        printf("success\n");
        PrintList(L);
    } else{
        printf("failed\n");
    }
    printf("delete Linear table element\n");
    ElemType del;
    ret= ListDel(L,1,del);
    if(ret){
        printf("success\n");
        PrintList(L);
    } else{
        printf("failed\n");
    }
    printf("find Linear table element\n");
    int result;
    result=ListFind(L,2);
    if(result != 0){
        printf("success\n");
        printf("position is %d\n",result);  // 打印元素位置
    } else{
        printf("failed\n");
    }
    printf("update Linear table element\n");
    ret= ListUpdate(L,2,18);
    if(ret){
        printf("success\n");
        PrintList(L);
    } else{
        printf("failed\n");
    }
    return 0;
}
F:\Computer\Project\practice\10\10.1-linear_table\cmake-build-debug\10_1_linear_table.exe
init Linear table
insert Linear table element
success
  1 50  2  3
delete Linear table element
success
 50  2  3
find Linear table element
success
position is 2
update Linear table element
success
 50 18  3

进程已结束,退出代码为 0

第二节:线性表的链式表示

单链表

逻辑上相邻的两个元素在物理位置上不相邻。

单链表结点的定义:

typedef struct LNode{ // 单链表结点类型
    ElemType data;  // 数据域
    struct LNode *next;  // 指针域
}LNode,*LinkList;

头指针:链表中第一个节点的存储位置,用来标识单链表。

头结点:在单链表第一个节点之前附加的一个结点,为了操作上的方便。

若链表有头结点,则头指针永远指向头结点,不论链表是否为空,头指针均不为空,头指针是链表的必须元素,它标识一个链表。

头结点是为了操作的方便而设立的,其数据域一般为空,或者存放链表的长度。有头结点后,对在第一结点前插入和删除第一结点的操作就统一了,不需要频繁重置头指针。但头结点不是必须的

优缺点对比

插入操作

创建新结点

q=(LNode*)malloc(sizeof(LNode))
q->data=x;

头插入和中间插入

q->next=p->next;
p->next=q;

尾插入

p->next=q;
q->next=NULL;

说明:q是新插入的元素。p是指针指向的元素。

删除操作

p=GetElem(L,i-1); // 查找删除位置的前驱结点
p->next=q->next;
free(q);

说明:q是要删除的元素,p是指针指向的元素。删除完后要释放空间。

代码示例

按序号查找结点值的算法如下:

LNode *p=L->next;
int j=1;
while(p && j<i){
    p=p->next;
    j++;
}
return p;

按值查找结点的算法如下:

LNode *p=L->next;
while(p!=NULL && p->data!=e){
    p=p->next;
}
return p;

说明:L是头指针,用来指向头结点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/58175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python中的序列(列表、元组、字符串)的切片操作

目录 一.序列 二. 序列常用操作——切片 注意 演示 一.序列 序列是指:内容连续、有序&#xff0c;可使用下标索引的一类数据容器 列表、元组、字符串&#xff0c;均可以可以视为序列。 二. 序列常用操作——切片 序列支持切片&#xff0c;即:列表、元组、字符串&#xf…

看卡塔尔世界杯,diff一下足球比赛与软件开发

diff一下足球比赛与软件开发吐槽世界杯E组&#xff01;类比软件开发与足球比赛教练与架构师的作用新技术——半自动越位技术世界杯冠军吐槽世界杯E组&#xff01; 最近博主看了多场世界杯比赛&#xff0c;看的我心力交瘁&#xff0c;欲哭无泪。 从日本与哥斯达黎加那场比赛开始…

算法刷题打卡第34天:有效的井字游戏

有效的井字游戏 难度&#xff1a;中等 给你一个字符串数组 boardboardboard 表示井字游戏的棋盘。当且仅当在井字游戏过程中&#xff0c;棋盘有可能达到 boardboardboard 所显示的状态时&#xff0c;才返回 truetruetrue 。 井字游戏的棋盘是一个 3 x 3 数组&#xff0c;由字…

MYSQL 中连接的使用

文章目录0 写在前面1 语法说明2 SQL准备3 举例说明3.1 内连接3.2 左连接3.3 右连接4 写在最后0 写在前面 实际业务中&#xff0c;查询数据库大多都是多表链接查询&#xff0c;所以MYSQL的连接的使用非常重要。 连接有三种: INNER JOIN&#xff08;内连接,或等值连接&#xff0…

[附源码]计算机毕业设计疫情背景下社区互助服务系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Git基本使用

目录 一、Git基础 1.Git与Github 2.注册Github账号并安装Git 二、Git的使用 1.本地仓库 进行全局配置&#xff1a; 创建仓库&#xff1a; Git常用操作指令&#xff1a; 版本回退&#xff1a; 2.远程仓库 两种常规使用方式&#xff1a; 分支管理&#xff1a; 冲突的产生…

python http模块快速搭建“简单”服务器笔记

极简运行 python -m http.sever或 # test.py import http.server import socketserverPORT 8000Handler http.server.SimpleHTTPRequestHandlerwith socketserver.TCPServer(("", PORT), Handler) as httpd:print("serving at port", PORT)httpd.serve…

m基于matlab的光通信的信道估计,均衡,抑制papr误码率仿真,对比ZF,RLS,MMSE三种算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 可见光通信的信道估计&#xff0c;均衡&#xff0c;抑制papr。 不考虑光信道&#xff0c;用传统的无线通信的OFDM的信道估计&#xff0c;均衡&#xff0c;抑制papr 信道估计&#xff0c;均衡最…

解决Windows RDP远程桌面连接同时多用户连接不互踢不干扰问题及rdp wrapper windows版本不受支持问题.

注意: 如果你当前正在通过RDP方式远程连接到你要更改设置的目标计算机,请在目标计算机上安装其他远程控制软件.防止RDP因在此过程中挂掉无法连接. 下载: 使用GitHub - stascorp/rdpwrap: RDP Wrapper Library开源软件 转到Release 最新版本的是1.6.2,原作者没有更新的了.好…

MySQL中count(*)和information_schema.tables中的table_rows值不相同

前两天我还在高高兴兴地写了一篇文章《一条SQL查询出MySQL数据库中所有表的数据量大小》&#xff0c;心想这也太方便了&#xff0c;只用一条SQL就能统计出所有表的数据量&#xff0c;但没想到&#xff0c;最终还是翻车了。。。 翻车过程如下&#xff1a; 有一张表&#xff0c…

【多目标进化优化】 MOEA 测试函数

声明 本文内容来源于 《多目标进化优化》 郑金华 邹娟著&#xff0c;非常感谢两位老师的知识分享&#xff0c;如有侵权&#xff0c;本人立即删除&#xff0c;同时在此表示&#xff0c;本文内容仅学习使用&#xff0c;禁止侵权&#xff0c;谢谢&#xff01; 注&#xff1a;本文…

HTML+CSS制作简单的家乡网页 ——我的家乡介绍广东 web前端期末大作业

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

基于STM32单片机的温度报警器(数码管)(Proteus仿真+程序)

编号&#xff1a;26 基于STM32单片机的温度报警器&#xff08;数码管) 功能描述&#xff1a; 本设计由STM32F103单片机最小系统DS18B20温度传感器数码管显示模块声光报警模块独立按键组成。 1、主控制器是STM32F103单片机 2、DS18B20温度传感器测量温度 3、数码管显示温度值&…

数字化改革“1612”详解

背景 2021年2月18日&#xff0c;浙江省开始数字化改革建设&#xff0c;通过一年的建设&#xff0c;取得了光辉成绩。2022年2月28日&#xff0c;在省数字化改革推进大会&#xff0c;回顾一年来数字化改革的主要成效&#xff0c;研究部署2022年数字化改革目标任务&#xff0c;在…

Spring框架(六):SpringTransaction事务的底层原理、xml配置和注解配置

SpringTransaction事务的底层原理、xml配置和注解配置引子Spring事务入门搭建Test环境基于XML的方式配置事务Spring事务的隔离级别Spring事务的传播行为通过Annotation方式配置Spring的事务引子 痛定思痛&#xff0c;主要问题出现在自己雀氏不熟悉框架底层、一些面试题&#x…

【源码分析】Springboot启动流程源码分析

1.简介 springboot版本&#xff1a;2.7.2 SpringApplication类是用来执行Spring框架启动的引导类。 有两种方式可以进行启动引导&#xff1a; 通过静态方法SpringApplication.run启动。先创建SpringApplication实例&#xff0c;在调用的实例方法run进行启动。 无论是以上哪种…

资源管理管理

资源管理目录概述需求&#xff1a;设计思路实现思路分析1.PMI hr的理念2.双因素的理论3.马斯洛的需求层析理论4.延伸5.X&#xff0c;Y理论Z 理论期望理论&#xff1a;亚当斯公共理论边际福利&#xff0c;光环效应&#xff0c;额外待遇&#xff0c;皮的原理&#xff0c;KISS原理…

阿里P9大牛带你在简历上写精通Spring与Boot高级功能

前言 蓦然回首自己做开发已经十年了&#xff0c;这十年中我获得了很多&#xff0c;技术能力、培训、出国、大公司的经历&#xff0c;还有很多很好的朋友。但再仔细一想&#xff0c;这十年中我至少浪费了五年时间&#xff0c;这五年可以足够让自己成长为一个优秀的程序员&#…

QT - 模型与视图

经典MVC模式中&#xff0c;M是指业务模型&#xff0c;V是指用户界面&#xff0c;C则是控制器&#xff0c;使用MVC的目的是将M和V的实现代码分离&#xff0c;从而使同一个程序可以使用不同的表现形式。其中&#xff0c;View的定义比较清晰&#xff0c;就是用户界面。 MVC 不是一…

银行 测试|测试开发 面试真题|面经 汇总

招银测开面经 一面 1.面向对象3大特征 2.java是否能多继承&#xff0c;怎么实现多继承 3.抽象类 4.数据库特性&#xff0c;隔离级别 5.sql语句查找 6.static关键字的使用 7.手撕&#xff1a;寻找字符串出现频率最高的字符 8.代码改进和测试 二面 1.先闲聊了几句&…