顺序表和链表知识点

1 顺序表

顺序表是指用一段物理地址连续的空间去存储数据的线性结构。

顺序表有两种:静态顺序表,动态顺序表。

1.1 静态顺序表结构体定义

typedef int ElemDataSL;typedef struct SequeList {ElemDataSL arr[100];int size;
}SL;

静态顺序表在创建结构体的时候就已经把容量固定,后期空间不够,不允许增加新空间,所以并不方便实际使用。

例子:通讯录(C语言实现)-CSDN博客

1.2 动态顺序表结构体定义

typedef int ElemDataSL;typedef struct SequeList {ElemDataSL* arr;int size;int capatity;
}SL;

 动态顺序表在创建结构体的时候定义了arr的指针作为一段连续内存空间的首地址,如果有需要可以用realloc开辟新空间进行扩容处理。

1.2.1 接口声明

//初始化
void InitSequeList(SL* s);
//尾插
void SequeListPushBack(SL* s,ElemDataSL num);
//尾删
void SequeListPopBack(SL* s);
//头插
void SequeListPushFront(SL* s, ElemDataSL num);
//头删
void SequeListPopFront(SL* s);
//pos处插
void SequeListPushInsert(SL* s,ElemDataSL num,int pos);
//pos处删
void SequeListPopInsert(SL* s,int pos);
//显示
void SequeListShowData(SL* s);
// 顺序表删除pos位置的值
void SequeListErase(SL*s, size_t pos);
// 顺序表销毁
void SequeListDestory(SL* s);

1.2.2 初始化

//初始化
void InitSequeList(SL* s) {assert(s);s->arr = (ElemDataSL*)malloc(DefaultData * sizeof(ElemDataSL));s->capatity = DefaultData;s->size = 0;
}

1.2.3 尾插

//尾插
void SequeListPushBack(SL* s,ElemDataSL num) {assert(s);AddCapatity(s);s->arr[s->size] = num;s->size++;
}

 1.2.4 尾删

//尾删
void SequeListPopBack(SL* s)
{assert(s);s->size--;
}

1.2.5 头插

//头插
void SequeListPushFront(SL* s,ElemDataSL num) {AddCapatity(s);for (int i = s->size-1; i >=0; i--){s->arr[i + 1] = s->arr[i];}s->arr[0] = num;s->size++;
}

1.2.6 头删

//头删
void SequeListPopFront(SL* s)
{for (int i = 0; i <= s->size - 1; i++){s->arr[i] = s->arr[i + 1];}s->size--;
}

1.2.7 中间插入

//pos处插
void SequeListPushInsert(SL* s,ElemDataSL num,int pos)
{AddCapatity(s);for (int i = s->size - 1; i >= pos-1; i--){s->arr[i + 1] = s->arr[i];}s->arr[pos-1] = num;s->size++;
}

1.2.8 中间删除

//pos处删
void SequeListPopInsert(SL* s, int pos) {for (int i = pos-1; i <= s->size - 1; i++){s->arr[i] = s->arr[i + 1];}s->size--;
}

1.2.9 打印顺序表

//显示
void SequeListShowData(SL* s)
{assert(s);for (int i = 0; i < s->size; i++){printf("%d ", s->arr[i]);}printf("\n");
}

1.3 顺序表销毁

// 顺序表销毁
void SequeListDestory(SL* s) {free(s->arr);s->arr = NULL;
}

顺序表优点:可以利用随机访问。

缺点:开辟空间可能会导致空间浪费,增删改查的时间复杂度为O(N)。

2 链表

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

注意:

1、链式结构在逻辑上是连续的,但在物理上非连续。

2、在堆上开辟空间。

3、在堆上申请空间,按照一定策略进行的,两次开辟的空间可能连续也可能不连续。

2.1 单链表

无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。

2.2 接口声明

typedef int SLDATATYPE;
typedef struct SListNode {int data;struct SListNode* next;
}SListNode;
//尾插
void SListPushBack(SListNode** pphead, SLDATATYPE num);
//尾删
void SListPopBack(SListNode* phead);
//头插
void SListPushFront(SListNode** pphead, SLDATATYPE num);
//头删
void SListPopFront(SListNode* phead);
//查找
SListNode* SListFind(SListNode* phead, SLDATATYPE num);
//中间后插
void SListInsertAfter(SListNode* pos, SLDATATYPE num);
//中间删
void SListEraseAfter(SListNode* pos);
//打印
void SListPrint(SListNode* phead);
//销毁链表
void SListDistory(SListNode** phead);

2.3 尾插

//尾插
void SListPushBack(SListNode* *pphead, SLDATATYPE num) {SListNode* NewNode = BuySListNode(num);if (*pphead == NULL){*pphead= NewNode;}else{	SListNode* tail = *pphead;while (tail->next!=NULL){tail = tail->next;}tail->next= NewNode;}
}

2.4 尾删

//尾删
void SListPopBack(SListNode** phead)
{SListNode* tail = *phead;SListNode* prev = tail;if (*phead == NULL){return;}else if ((*phead)->next == NULL){free(*phead);*phead = NULL;}else{while (tail->next != NULL){prev = tail;tail = tail->next;}free(tail);prev->next = NULL;}}

2.5 头插

//头插
void SListPushFront(SListNode** pphead, SLDATATYPE num)
{SListNode* newNode = BuySListNode(num);if ((*pphead) == NULL){*pphead = newNode;}else{newNode->next = *pphead;}*pphead = newNode;
}

2.6 头删

//头删
void SListPopFront(SListNode* *pphead)
{	SListNode* head = *pphead;if (head == NULL){return;}else if (head->next == NULL){*pphead = NULL;}else{(*pphead) = (*pphead)->next;free(head);}}

2.7 查找

SListNode* SListFind(SListNode* phead, SLDATATYPE num) {SListNode* ptr = phead;while (ptr){if (ptr->data == num){printf("%d找到了!\n",ptr->data);return  ptr;}ptr = ptr->next;}printf("%d没找到!\n",num);return NULL;
}

2.8 中间后插

void SListInsertAfter(SListNode* *pos, SLDATATYPE num)
{SListNode* newNode = BuySListNode(num);newNode->next = (*pos)->next;(*pos)->next = newNode;
}

2.9 中间后删

void SListEraseAfter(SListNode* pos)
{assert(pos);assert(pos->next);SListNode* next = pos->next;pos->next = next->next;free(next);
}

3 打印

//打印
void SListPrint(SListNode* phead)
{SListNode* cur = phead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

3.1 销毁链表

void SListDistory(SListNode** phead)
{assert(*phead);SListNode* next = (*phead)->next;while (next){free(*phead);*phead = next;next = next->next;}free(*phead);*phead = NULL;
}

单链表优点:需要增加多少个元素就开辟多少空间不会导致空间浪费,插入时间复杂度低。

缺点:不能随机访问,只能依次往后访问,无法实现从后往前。

2.2 双链表

头节点不存储有效数据。

2.2.1 接口声明

typedef int ListData;
typedef struct ListNode
{ListData data;struct ListNode* next;struct ListNode* prev;
}ListNode;
//链表创建
ListNode* ListCreate();
//尾插
void ListPushBack(ListNode* phead, ListData x);
//尾删
void ListPopBack(ListNode* phead);
//头插
void ListPushFront(ListNode* phead, ListData x);
//头删
void ListPopFront(ListNode* phead);
//查找
ListNode* ListFind(ListNode* phead, ListData x);
//中间插
void ListInsert(ListNode* pos,ListData x);
//中间删
void ListErase(ListNode* pos);
//显示
void ListPrint(ListNode* phead);
//清空链表
void ListClear(ListNode** phead);
//销毁链表
void ListDestory(ListNode* phead);

2.2.2 创建新节点 


ListNode* BuyListNode(ListData x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));node->data = x;node->next = NULL;node->prev = NULL;return node;
}

2.2.3 双链表创建

ListNode* ListCreate() {ListNode* phead = BuyListNode(0);phead->next = phead;phead->prev = phead;return phead;
}

2.2.4 尾插 

//尾插
void ListPushBack(ListNode* phead, ListData x)
{assert(phead);ListNode* tail = phead->prev;ListNode* newNode = BuyListNode(x);tail->next = newNode;newNode->prev = tail;newNode->next = phead;phead->prev = newNode;
}

 2.2.5 尾删

//尾删
void ListPopBack(ListNode* phead)
{assert(phead->next != phead);/*ListNode* tail = phead->prev;ListNode* tailPrev = tail->prev;tailPrev->next = phead;phead->prev = tailPrev;*/ListErase(phead->prev);
}

2.2.6 头插

//头插
void ListPushFront(ListNode* phead, ListData x)
{ListNode* newNode = BuyListNode(x);ListNode* pheadNext = phead->next;phead->next = newNode;newNode->prev = phead;newNode->next = pheadNext;pheadNext->prev = newNode;
}

2.2.7 头删 

//头删
void ListPopFront(ListNode* phead)
{ListNode* pheadNext = phead->next;phead->next = pheadNext->next;pheadNext->next->prev = phead;free(pheadNext);
}

2.2.8 查找

//查找
ListNode* ListFind(ListNode* phead, ListData x)
{ListNode* pos = NULL;ListNode* cur = phead->next;while (cur != phead){if (cur->data == x){pos = cur;break;}cur = cur->next;}return pos;
}

2.2.9 中间插

//中间插
void ListInsert(ListNode* pos, ListData x)
{assert(pos);/*ListNode* newNode = BuyListNode(x);ListNode* posPrev = pos->prev;newNode->next = pos;pos->prev = newNode;posPrev->next = newNode;newNode->prev = posPrev;*/ListPushFront(pos->prev, x);
}

2.3 中间删

//中间删
void ListErase(ListNode* pos)
{ListNode* posPrev = pos->prev;ListNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos);
}

2.3.1 显示

//显示
void ListPrint(ListNode* phead)
{assert(phead);ListNode* tail = phead->next;while (tail != phead){printf("%d ", tail->data);tail = tail->next;}printf("\n");
}

2.3.2 清空链表

void ListClear(ListNode** phead)
{ListNode* cur = (*phead)->next;while (cur != *phead){ListNode* next = cur->next;free(cur);cur = next;}(*phead)->next = *phead;(*phead)->prev = *phead;
}

2.3.3 销毁链表

//销毁链表
void ListDestory(ListNode** phead)
{ListClear(phead);free(*phead);
}

双链表优点:插入时间复杂度比单链表更低,可以前驱访问。

缺点:不能随机访问。

 3 顺序表和链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,物理上不一定连续
随机访问支持O(1)不支持O(N)
任意位置插入或者删除元素可能需要搬移元素,效率低O(N)只需修改指针指向
插入动态顺序表,空间不够时需要扩容没有容量概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

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

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

相关文章

【 html+css 绚丽Loading 】000026 五行吞灵盘

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…

网络安全领域含金量最高的5大赛事,每个网安人的梦!

做网络安全一定要知道的5大赛事&#xff0c;含金量贼高&#xff0c;如果你能拿奖&#xff0c;国内大厂随你挑&#xff0c;几乎是每个有志网安人的梦&#xff01; 一、 DEF CON CTF&#xff08;DEF CON Capture the Flag&#xff09; DEF CON CTF是DEF CON黑帽大会上的一项著名…

江协科技STM32学习- P7 GPIO输入

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

数据结构(树、平衡树、红黑树)

目录 树 树的遍历方式 平衡二叉树 旋转机制 左旋 右旋 旋转实例 左左 左右 右右 右左 总结 红黑树 树 相关概念 节点的内部结构如下 二叉树与二叉查找树的定义如下 树的遍历方式 前序遍历&#xff1a;当前节点&#xff0c;左子节点&#xff0c;右子结点 中序遍…

string的模拟实现与深浅拷贝

在上一章中可以看见&#xff0c;string类函数的基本实现和用法&#xff0c;在本文。来用基础的语言来模拟实现string类&#xff0c;来了解一下他们的基础底层&#xff1b; 在VS中string&#xff0c;我们可以看见&#xff0c;实现VS的类成员很多&#xff0c;很麻烦&#xff1b; …

【STM32】电容触摸按键

电容按键就是酷&#xff0c;但据我使用过电容按键版的洗澡计费机子后&#xff0c;一生黑&#xff08;湿手优化没做好的电容按键简直稀碎&#xff09;。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 触摸按…

Zookeeper官网Java示例代码解读(一)

2024-08-22 1. 基本信息 官网地址&#xff1a; https://zookeeper.apache.org/doc/r3.8.4/javaExample.html 示例设计思路 Conventionally, ZooKeeper applications are broken into two units, one which maintains the connection, and the other which monitors data. I…

【C++ Primer Plus习题】7.5

问题: 解答: #include <iostream> using namespace std;int function(int n) {if (n 0)return 1;if (n 1)return 1;return n* function(n - 1); }int main() {int value 0;while (true){cout << "请输入数字:";cin >> value;cout << val…

华为Huawei路由器交换机SSH配置

华为设备的SSH登录配置需要5个步骤&#xff0c;示例如下&#xff1a; 一、配置命令 使能SSH功能 stelnet server enable生成公钥 rsa local-key-pair create 1024配置AAA用户密码及相应授权 aaalocal-user xxx password cipher xxxyyy1234local-user xxx privilege level …

ADB 获取屏幕坐标,并模拟滑动和点击屏幕

本文声明:本文是参考https://blog.csdn.net/beyond702/article/details/69258932编制。同时,补充了在windows系统模式下,详细的获取屏幕坐标的步骤。 1.判断设备与windows电脑USB连接是否正常 在CMD窗口输入命令:ADB devices,按ENTER键,输出如下结果,则表示连接正常。 …

Prometheus+Grafana监控数据可视化

上一篇文章讲了prometheus的简单使用&#xff0c;这一篇就先跳过中间略显枯燥的内容&#xff0c;来到监控数据可视化。 一方面&#xff0c;可视化的界面看着更带劲&#xff0c;另一方面&#xff0c;也更方便我们直观的查看监控数据&#xff0c;方便后面的学习。 Grafana安装与…

DIFFUSION 系列笔记| Latent Diffusion Model、Stable Diffusion基础概念、数学原理、代码分析、案例展示

目录 Latent Diffusion Model LDM 主要思想 LDM使用示例 LDM Pipeline LDM 中的 UNET 准备时间步 time steps 预处理阶段 pre-process 下采样过程 down sampling 中间处理 mid processing 上采样 upsampling 后处理 post-process LDM Super Resolution Pipeline…

Redis基本全局命令

文章目录 get和setkeysexistsdelexpirettltype redis全局命令&#xff1a; redis支持很多种数据结构&#xff0c;整体上来说。redis是键值对结构&#xff0c;key固定就是字符串&#xff0c;value实际上就会有很多种&#xff0c;比如说&#xff1a; 字符串哈希表列表有序集合 …

住宅物业满意度计算方式中满意率和满意度指数的区别

满意率和满意度指数是用于计算住宅物业满意度的两种不同方式&#xff0c;它们的区别如下&#xff1a; 1、满意率&#xff1a;满意率是通过计算满意的居民人数与总参与调查的居民人数之间的比例来衡量满意度。它以百分比形式表示&#xff0c;可以直观地了解居民对物业管理的整体…

集运系统如何多维度展现企业业务情况?

在集运行业&#xff0c;数据是企业决策的重要依据。为了在竞争中保持优势&#xff0c;企业需要一套高效、灵活且可靠的管理工具来应对市场的快速变化。易境通集运系统以其全面而精细的统计报表功能&#xff0c;成为企业决策优化和业务增长的重要助手。 易境通集运系统https://…

使用在AMD GPU上运行的ROCm进行大语言模型的自然语言处理任务

Performing natural language processing tasks with LLMs on ROCm running on AMD GPUs — ROCm Blogs 在这篇博客中&#xff0c;您将学习如何使用在AMD的Instinct GPU上运行的ROCm进行一系列流行且有用的自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;使用不同的大…

新手该如何选择与小程序定位相关的关键词

关键词的优化是提高小程序排名的关键步骤之一&#xff0c;所以如何选择与小程序定位相关的关键词是一个很重要的过程&#xff0c;需要考虑多个因素以确保关键词既符合小程序的业务特性&#xff0c;又能吸引目标用户。以下是一些具体的步骤和建议&#xff1a; 1. 深入了解小程序…

Go发布自定义包

1、初始化go.mod go mod init github.com/xumeng03/images2、编写包内容 这里只是一个简单的压缩jpg/jpeg图片例子&#xff0c;代码参考 https://github.com/disintegration/imaging 2.1、fs.go package imagesimport ("image""io""os""p…

Vue3中的defineExpose的认识

文章目录 defineExpose子组件父组件&#xff1a;总结&#xff1a; defineExpose 使用 <script setup> 的组件是默认关闭的——即通过模板引用或者 $parent 链获取到的组件的公开实例&#xff0c;** 不会 **暴露任何在 <script setup> 中声明的绑定。 可以通过 def…

OpenCV几何图像变换(10)透视变换函数warpPerspective()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 warpPerspective 函数使用指定的矩阵对源图像进行透视变换&#xff1a; dst ( x , y ) src ( M 11 x M 12 y M 13 M 31 x M 32 y M 33 , M…