数据结构C语言之线性表

发现更多计算机知识,欢迎访问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;elsereturn 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;elsereturn 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;    //头结点指针域置NULLfor (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域置为NULLr->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; // 先后指针域置NULLfor (int i = 0; i < n; i++) // 循环创建数据结点{s = (DlinkNode*)malloc(sizeof(DlinkNode)); // 创建数据结点ss->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)); // 创建数据结点ss->data = a[i];r->next = s; s->prior = r;      //将s结点插入到r结点之后r = s;                          //r指向尾结点}r->next = NULL;
}

2.6总结

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

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

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

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

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

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

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

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

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis篇---第三篇

系列文章目录 文章目录 系列文章目录前言一、为什么 Redis 需要把所有数据放到内存中?二、Redis 的同步机制了解是什么?三、pipeline 有什么好处,为什么要用 pipeline?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到…

免费图像压缩工具分享:15 个最佳免费图像压缩工具

您想在将图像上传到网上之前对其进行压缩吗&#xff1f;优化摄影网站的图像将有助于您的网站加载速度更快。而且&#xff0c;更快的加载速度意味着更好的搜索引擎排名&#xff01;在本指南中&#xff0c;我们将分享用于图像压缩的最佳免费图像优化工具。 许多照片编辑程序&…

有趣的按钮分享

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 广告打完&#xff0c;我们进入正题&#xff0c;先看效果&#xff1a; 废话不多&#xff0c;上源码&#xff1a; <button class&quo…

DeepMind发布新模型Mirasol3B:更高效处理音频、视频数据

Google DeepMind日前悄然宣布了其人工智能研究的重大进展&#xff0c;推出了一款名为“Mirasol3B”的新型自回归模型&#xff0c;旨在提升对长视频输入的理解能力。该新模型展示了一种颠覆性的多模态学习方法&#xff0c;以更综合和高效的方式处理音频、视频和文本数据。 Googl…

数据加解密系统(揭秘数据解密的关键技术)

数据加解密系统是一种用于保护数据安全的系统&#xff0c;它可以将数据加密以防止未经授权的访问和数据泄露&#xff0c;同时也可以将已加密的数据解密以供授权用户使用。 随着网络技术和电子商务的不断发展&#xff0c;数据安全问题越来越受到人们的关注。数据加解密系统被广泛…

【数学】距离函数(未完)

文章目录 一、声明二、无符号距离函数 (Unsigned Distance Function, UDF)Wasserstein Distance / Earth Movers Distance ☆欧氏距离 (Euclidean Distance)马氏距离 (Mahalanobis Distance)带权重的最近邻距离&#xff08;Weighted Nearest Neighbor Distance&#xff09;Cham…

智慧党建小程序源码系统+在线考试+缴费+学习 功能强大 带完整的前后端搭建教程

“智慧党建”是现代社会党建工作的一种新理念。它是运用互联网、大数据等新一代信息技术&#xff0c;实现党建信息资源融合共享&#xff0c;稳步提升新时代党建科学化水平。促使党的建设多维度全覆盖、党建措施智慧生成的实现&#xff0c;从而提升党的执政能力和治理能力。下面…

PY32F002B从压缩包到实现串口printf输出

最近学习使用芯领的PY32F002B开发板&#xff0c;记录学习历程供有同样需求的人参考。 本文主要讲述利用开发板实现printf语句串口输出。 开发环境的初步搭建 官方提供了一个压缩文件&#xff0c;文件名py32f002B_231026.zip&#xff0c; 链接&#xff1a;https://pan.baidu.c…

JPA整合Sqlite解决Dialect报错问题, 最新版Hibernate6

前言 我个人项目中&#xff0c;不想使用太重的数据库&#xff0c;而内嵌数据库中SQLite又是最受欢迎的&#xff0c; 因此决定采用这个数据库。 可是JPA并不支持Sqlite&#xff0c;这篇文章就是记录如何解决这个问题的。 原因 JPA屏蔽了底层的各个数据库差异&#xff0c; 但是…

μC/OS-II---消息邮箱管理2(os_mbox.c)

目录 消息邮箱发送&#xff08;扩展&#xff09;从消息邮箱获取/无等待消息邮箱状态查询消息邮箱中断等待用邮箱作为二值信号量&#xff08;无&#xff09;用邮箱实现延时&#xff08;无&#xff09; 消息邮箱发送&#xff08;扩展&#xff09; #if OS_MBOX_POST_OPT_EN > …

苹果手机怎么转移通讯录?简单操作方法来了!

通讯录是手机中存储联系人信息的应用程序&#xff0c;它可以帮助用户方便快捷地进行通讯和信息交流。通讯录记录了我们的亲朋好友、同事等重要人物的联系方式。 如果因更换手机而丢失通讯录&#xff0c;可能会对我们的日常生活和社交带来不便。苹果手机怎么转移通讯录&#xf…

基于PyTorch搭建你的生成对抗性网络

前言 你听说过GANs吗&#xff1f;还是你才刚刚开始学&#xff1f;GANs是2014年由蒙特利尔大学的学生 Ian Goodfellow 博士首次提出的。GANs最常见的例子是生成图像。有一个网站包含了不存在的人的面孔&#xff0c;便是一个常见的GANs应用示例。也是我们将要在本文中进行分享的…