数据结构C语言之线性表

news2024/11/27 18:51:04

发现更多计算机知识,欢迎访问Cr不是铬的个人网站

1.1线性表的定义

线性表是具有相同特性的数据元素的一个有限序列 对应的逻辑结构图形:

file

从线性表的定义中可以看出它的特性:

(1)有穷性:一个线性表中的元素个数是有限的

(2)一致性:一个线性表中所有元素的性质相同,即数据类型相同

(3)序列性:各个元素的相对位置是线性的

1.2线性表的抽象数据类型描述

(如下图所示)

file

那为什么要引进这个数据结构呢?那就不得不谈谈它的作用了。

线性表的作用体现在两个方面:

a. 当一个线性表实现后,程序员加油直接使用它来存放数据,即作为存放数据的容器

b.使用线性表的基本运算来完成更复杂的运算

2.1线性表的顺序存储结构——顺序表

线性表的顺序存储结构简称为顺序表

file

(如图为线性表到顺序表的映射)

需要注意的是顺序表采用数组进行实现,但是不是任意数组可以作为一个顺序表,二者运算是不同的

​ 下图为顺序表的存储示意图

file

2.2顺序表的基本运算实现

(1)结构体SqList定义

//数据元素
typedef int ElemType;
//结构体
typedef struct
{
    ElemType data[MaxSize];
    //数据长度
    int length;
}SqList;

(2)建立顺序表

//建立顺序表
void CreateList(SqList*& L, ElemType a[], int n)
{
    int i = 0, k = 0;
    //记得一定要分配内存空间 
    L = (SqList*)malloc(sizeof(SqList));
    while (i < n)
    {
        //将a[i]存储到L中
        L->data[k] = a[i];
        k++; i++;
    }
    L->length = k;
}

(3)初始化线性表

void InitList(SqList*& L)
{
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0; //置空线性表的长度为0
}

(4)销毁线性表

void DestroyList(SqList*& L)
{
    free(L);//释放L所指的顺序表空间
}

(5)判断是否为空

bool ListEmpty(SqList* L)
{
    return(L->length == 0);
}

(6)求线性表长度

int ListLength(SqList* L)
{
    return (L->length);
}

(7)求表中某个值

bool GetElem(SqList* L, int i, ElemType& e)
{
    if (i<1 || i > L->length)
        return false;
    e = L->data[i - 1];
    return true;    //成功找到元素返回true
}

(8)按照元素值查找

int LocateElem(SqList* L,ElemType e)
{
    int i = 0;
    while (i < L->length && L->data[i] != e)
        i++;
    if (i >= L->length)
        return 0;
    else
        return i + 1;        //返回逻辑序号
}

(9)输出线性表

void DisplayList(SqList* L)
{
    for (int i = 0; i < L->length; i++)
        printf("%d", L->data[i]);
    printf("\n");
}

(10)完整代码

#include<iostream>
using namespace std;
const int MaxSize = 1005;
typedef int ElemType;
typedef struct
{
    ElemType data[MaxSize];
    int length;
}SqList;

//建立顺序表
void CreateList(SqList*& L, ElemType a[], int n)
{
    int i = 0, k = 0;
    //记得一定要分配内存空间 
    L = (SqList*)malloc(sizeof(SqList));
    while (i < n)
    {
        L->data[k] = a[i];
        k++; i++;
    }
    L->length = k;
}
//初始化线性表
void InitList(SqList*& L)
{
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0; //置空线性表的长度为0
}
void DestroyList(SqList*& L)
{
    free(L);//释放L所指的顺序表空间
}
bool ListEmpty(SqList* L)
{
    return(L->length == 0);
}

int ListLength(SqList* L)
{
    return (L->length);
}
void DisplayList(SqList* L)
{
    for (int i = 0; i < L->length; i++)
        printf("%d", L->data[i]);
    printf("\n");
}
bool GetElem(SqList* L, int i, ElemType& e)
{
    if (i<1 || i > L->length)
        return false;
    e = L->data[i - 1];
    return true;    //成功找到元素返回true
}
int LocateElem(SqList* L,ElemType e)
{
    int i = 0;
    while (i < L->length && L->data[i] != e)
        i++;
    if (i >= L->length)
        return 0;
    else
        return i + 1;        //返回逻辑序号
}
bool ListInsert(SqList*& L, int i, ElemType e)
{
    int j;
    if (i < 1 || i >L->length + 1 || L->length == MaxSize)
        return false;
    i--;
    for (j = L->length; j > i; j--)
        L->data[j] = L->data[j - 1];
    L->data[i] = e;
    L->length++;
    return true;
}
bool ListDelete(SqList*& L, int i, ElemType& e)
{
    int j;
    //特判是否符合 
    if (i < 1 || i>L->length)
        return false;
    i--;
    for (int j = i; j < L->length - 1; j++)
        L->data[j] = L->data[j + 1];
    L->length--;
    return true;
}
void delnodel(SqList*& L, ElemType x)
{
    int k = 0;
    for (int i = 0; i < L->length; i++)
        if (L->data[i] != x)
        {
            L->data[k] = L->data[i];
            k++;
        }
    L->length = k;
}

}
int main() {
    SqList* L;
    int a[10] = { 7,5,7,7,9,1,6,2,4,8 };
    CreateList(L, a, 10);

    DisplayList(L);
}

2.3线性表的链式存储结构——链表

线性表的链式存储就是链表,每个链表存储点不仅包括数据域,还有指针域。

链表示意图如下:

file

2.4 单链表算法实现

(1)数据结构声明

typedef int ElemType;
typedef struct LinkNode
{
    ElemType data;        //存放元素值
    struct LinkNode* next;    //指向后继结点

}LinkNode;

建立单链表有两种方法:头插法和尾插法

(2)头插法

//建立单链表
void CreatListF(LinkNode*& L, ElemType a[], int n)
{
    LinkNode* s;
    //创建头结点 
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL;    //头结点指针域置NULL
    for (int i = 0; i < n; i++)
    {
        s = (LinkNode*)malloc(sizeof(LinkNode));//重新分配空间
        s->data = a[i];
        s->next = L->next;
        L->next = s;
    }
}

(3)尾插法

void CreatListR(LinkNode*& L, ElemType a[], int n)
{
    LinkNode* s, * r;
    //创建头结点
    L = (LinkNode*)malloc(sizeof(LinkNode));
    r = L;                        //r始终指向尾结点,初始时指向头结点
    for (int i = 0; i < n; i++)
    {
        s = (LinkNode*)malloc(sizeof(LinkNode));//重新分配空间
        s->data = a[i];
        r->next = s;
        r = s;
    }
    //尾结点的nextt域置为NULL
    r->next = NULL;            
}

(4)初始化

void InitList(LinkNode*& L)
{
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL;
}

(5)销毁表

void DestroyList(LinkNode*& L)
{
    LinkNode* pre = L, * p = L->next;    //pre指向p的前驱结点
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);        //循环结束时p为NULL,pre指向尾结点
}

(6)输出表

void DispList(LinkNode* L)
{
    LinkNode* p = L->next;//指向头结点
    while (p!=NULL)
    {
        printf("%d", p->data);
        p = p->next;
    }
    printf("\n");
}

重点!!!

(7)链表的插入

bool ListInsert(LinkNode*& L, int i, ElemType e)
{
    int j = 0;
    LinkNode* p = L, * s;
    if (i <= 0)return false;//首结点的次序是一
    while (j < i - 1 && p != NULL)//找到第i-1个结点
    {
        j++;
        p = p->next;
    }
    if (p == NULL)
        return false;
    else
    {
        s = (LinkNode*)malloc(sizeof(LinkNode));
        //典中典
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
}

(8)删除某个元素

bool ListDelete(LinkNode*& L, int i, ElemType& e)
{
    int j = 0;
    LinkNode* p = L, * q;
    if (i <= 0)return false;//头结点是不计入其中的
    while (j < i - 1 && p != NULL)
    {
        j++;
        p = p->next;
    }        
    if (p == NULL)
        return false;
    else {
        q = p->next;
        if (q == NULL)
            return false;
        e = q->data;
        p->next = q->next;
        free(q);
        return true;
    }
}

最后介绍一下双链表

2.5双链表

(1)建立双链表

typedef int ElemType;
// 定义DlinkNode结构体
struct DlinkNode {
    int data;           // 数据域
    DlinkNode* prior;   // 前驱指针
    DlinkNode* next;    // 后继指针
};

同样的,双链表的建立也有头插法和尾插法

(2)头插法

// 定义CreateListF函数
void CreateListF(DlinkNode*& L, ElemType a[], int n)
{
    DlinkNode* s;
    L = (DlinkNode*)malloc(sizeof(DlinkNode)); // 创建头结点
    L->prior = L->next = NULL; // 先后指针域置NULL
    for (int i = 0; i < n; i++) // 循环创建数据结点
    {
        s = (DlinkNode*)malloc(sizeof(DlinkNode)); // 创建数据结点s
        s->data = a[i];
        s->next = L->next; // 将S插到头结点之后
        if (L->next != NULL)
            L->next->prior = s;
        L->next = s;
        s->prior = L;
    }
}

(3)尾插法

void CreateListR(DlinkNode*& L, ElemType a[], int n)
{
    DlinkNode* s,*r;
    L = (DlinkNode*)malloc(sizeof(DlinkNode)); // 创建头结点
    r = L;          //r始终指向尾结点,开始时指向头结点
    for (int i = 0; i < n; i++) // 循环创建数据结点
    {
        s = (DlinkNode*)malloc(sizeof(DlinkNode)); // 创建数据结点s
        s->data = a[i];
        r->next = s; s->prior = r;      //将s结点插入到r结点之后
        r = s;                          //r指向尾结点
    }
    r->next = NULL;
}

2.6总结

线性表是一种基础且重要的数据结构,常见的线性表有三种实现方式:顺序表、单链表和双链表。

​ 本文对这三种线性表的实现方式及特点做一个简要总结:

一、顺序表顺序表是将逻辑顺序上相邻的数据元素存储在物理位置上也相邻的存储单元中,通常使用数组来实现。- 特点:定位直接,通过下标操作即可快速访问任一位置的节点;实现简单。

缺点:插入删除需要移动大量元素,效率低;存储空间固定,扩容不灵活。

二、单链表单链表通过链式存储结构实现,每个节点除存储数据外,还储存下一个节点的地址信息。

-特点:存储灵活,可动态扩展,插入删除简单,效率高。-

缺点:访问任一节点需要从头结点遍历,无法直接定位

三、双链表双链表相比单链表,每个节点增加一个指向前驱节点的指针,实现双向链表。-

特点:可双向遍历链表,操作更灵活。-

缺点:每个节点存储空间略大于单链表。

综上,三种线性表各有特点,使用需根据具体场景需求选择合适的数据结构。顺序表操作简单,链表存储灵活,双链表可以双向访问。开发时需要权衡效率与实现难度,选择最优实现。

本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

Homography详解在MVSNet中的应用

Homography&#xff08;单应性变换&#xff09;是计算机视觉中的一个重要概念&#xff0c;用于描述两个平面之间的透视关系。在图像处理和计算机视觉中&#xff0c;Homography通常表示两个平面之间的投影关系&#xff0c;这种关系可以通过一个3x3的矩阵来表示。 在数学上&…

YB4019是一款完整的单电池锂离子恒流/恒压线性充电器电池

YB4019 耐压18V 1A线性双节8.4V 锂电充电芯片 概述&#xff1a; YB4019是一款完整的单电池锂离子恒流/恒压线性充电器电池。底部采用热增强ESOP8封装&#xff0c;外部组件数量低使YB4019成为便携式应用的理想选择。此外&#xff0c;YB4019设计用于在USB电源规格范围内工作。Y…

洗袜子的洗衣机哪款好?内衣洗衣机测评

随着人们的生活水平的提升&#xff0c;越来越多小伙伴来开始追求更高的生活水平&#xff0c;一些智能化的小家电就被发明出来&#xff0c;而且内衣洗衣机是其中一个。现在通过内衣裤感染到细菌真的是越来越多&#xff0c;所以我们对内衣裤的清洗频次会高于普通衣服&#xff0c;…

File类和IO流

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

2024苹果笔记本清理内存清理优化工具CleanMyMac X

在使用苹果笔记本电脑的过程中&#xff0c;清理内存是保持电脑运行流畅的重要步骤之一。当我们使用大量的应用程序和文件时&#xff0c;电脑的内存可能会被占满&#xff0c;导致系统变慢甚至出现崩溃的情况。因此&#xff0c;了解如何清理苹果笔记本的内存是非常必要的。本文将…

代码随想录 Day47 动态规划15 LeetCode T583 两个字符串的删除操作 T72 编辑距离

LeetCode T583 两个字符串的删除操作 题目链接:583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 本题有两个思路 1.使用两个字符串的长度之和-2*最长公共子串(换汤不换药) 代码随想录Day45 动态规划13 LeetCode T1143最长公共子序列 T1135 不相交…

适用于 Mac 的 10 款最佳数据恢复工具

对于依赖计算机处理重要文件&#xff08;无论是个人照片还是重要业务文档&#xff09;的任何人来说&#xff0c;数据丢失都可能是一场噩梦。 值得庆幸的是&#xff0c;有多种数据恢复工具专门用于Mac用户&#xff0c;可以帮助您恢复丢失或意外删除的文件。 在本文中&#xff0c…

Rust图形界面:eGUI的Panel布局

文章目录 Panel布局尺寸调节源码 Panel布局 eGUI提供面板堆叠的布局方案&#xff0c;即Panel布局。其布局逻辑是&#xff0c;根据当前面板指定的方向&#xff0c;尽可能地填充空间。 CentralPanel 占据屏幕剩余部分的空间SidePanel 占据屏幕两侧的空间&#xff0c;在具体调用…

【网络】TCP协议的相关实验

TCP协议的相关实验 一、理解listen的第二个参数1、实验现象2、TCP 半连接队列和全连接队列3、关于listen的第二个参数的一些问题4、SYN洪水Ⅰ、什么是SYN洪水攻击Ⅱ、如何解决SYN洪水攻击&#xff1f; 二、使用Wireshark分析TCP通信流程 一、理解listen的第二个参数 在编写TCP…

【23真题】无耻!“官方”假真题!害人!

这套华侨23真题是学弟给我从考场抄出来的版本&#xff0c;我刚刚做完解析&#xff01;后台就收到了另外一份“官方华侨23真题”的投稿。我本想对对回忆版&#xff0c;补充下题干。结果一对吓一跳&#xff01;竟然一道题都不一样&#xff01;给大家看下&#xff0c;真的好逼真&a…

《向量数据库指南》——TruLens + Milvus Cloud 构建RAG案例

具体案例 如前所述,RAG 配置选择可能对消除幻觉产生重大影响。下文中将基于城市百科文章构建问答 RAG 应用并展示不同的配置选择是如何影响应用性能的。在搭建过程中,我们使用 LlamaIndex 作为该应用的框架。大家可以在 Google Colab( https://colab.research.google.com/git…

Theory behind GAN

假如要生成一些人脸图&#xff0c;实际上就是想要找到一个分布&#xff0c;从这个分布内sample出来的图片像是人脸&#xff0c;分布之外生成的就不像人脸。而GAN要做的就是找到这个distribution。 在GAN之前用的是Maximum Likelihood Estimation。 Maximum Likelihood Estimat…

【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏2(附项目源码)

文章目录 先看本次实现的最终效果前言敌人生命值扣血测试&#xff0c;敌人死亡控制敌人动画敌人死亡动画敌人转向问题源码完结 先看本次实现的最终效果 前言 本期紧接着上一篇&#xff0c;本期主要内容是实现敌人血条、动画和行为逻辑。 敌人生命值 绘制血条UI 新建 publ…

快速入门:构建您的第一个 .NET Aspire 应用程序

##前言 云原生应用程序通常需要连接到各种服务&#xff0c;例如数据库、存储和缓存解决方案、消息传递提供商或其他 Web 服务。.NET Aspire 旨在简化这些类型服务之间的连接和配置。在本快速入门中&#xff0c;您将了解如何创建 .NET Aspire Starter 应用程序模板解决方案。 …

unity 烘焙的时候出现模型没有光影的情况

unity 烘焙的时候出现模型没有光影的情况 1.模型没有设置生成光照贴图 需要勾选模型的生成光照贴图UVs,然后应用 2.游戏对象没有勾选静态选项 点开静态下拉列表&#xff0c;选择 contribute GI

Accelerate 0.24.0文档 四:Megatron-LM

参考《Megatron-LM》 文章目录 一、Megatron-LM集成简介二、环境配置设置conda环境的步骤&#xff1a; 二、Accelerate Megatron-LM Plugin三、自定义训练过程四、检查点转换五、文本生成六、支持ROPE 、 ALiBi和Multi-Query Attention七、注意事项 一、Megatron-LM集成简介 在…

再谈谷歌GMS认证之Android 13

写在前面的话 2023年来到一个新的公司&#xff0c;传说中的做互联网金融即将上市的高大上公司。 入职后才发现就是做pos机设备的一个小厂 哎&#xff0c;什么命啊&#xff01; 工作和手机开发的工作重合度可以达到95%以上&#xff0c;我不想做手机&#xff0c;偏偏又干上…

全网首位数字军人“穆兰”惊艳亮相,与拓世法宝共同绘就未来社会图景

古有穆桂英、花木兰挂帅出征&#xff0c;今有全网首位虚拟数字军人“穆兰”展巾帼风采。今年国庆节后&#xff0c;中国军号在全网为解放军新闻传播中心数字记者暨全军首位超写实虚拟数字军人征名&#xff0c;历时一个多月&#xff0c;经过征名提交、评委初评、公众投票、专家共…

验证码识别之OCR识别

验证码识别&#xff1a; 背景&#xff1a; ​ 决定开一个专题给大家讲一下验证码识别&#xff0c;不要多想&#xff0c;我们不搞深度学习&#xff0c;知识用于攻破模拟登录的时候弹出的验证码&#xff0c;后续会给大家讲讲滑块等等&#xff0c;反爬虫策略如何应对。 好了&am…