数据结构【线性表篇】(二)

数据结构【线性表篇】(二)


文章目录

  • 数据结构【线性表篇】(二)
  • 前言
    • 为什么突然想学算法了?
    • 为什么选择码蹄集作为刷题软件?
  • 目录
  • 一、单链表
    • (一)、单链表的定义
    • (二)、单链表的建立
    • (三)、单链表的插入删除
    • (四)、单链表的查找
  • 二、主函数代码
  • 三、结语


前言

在这里插入图片描述

为什么突然想学算法了?

> 用较为“官方”的语言讲,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。
> 但从实际而言,是因为当下竞争压力逐渐增大,无论走哪一条路,都不免需要一些相对丰富的算法知识,是故,便产生了一个寒假巩固速成算法的计划,可能对于像我这种算法竞赛小白而言,几乎很难,但我仍然还是想尝试一下,毕竟,梦想还是要有的,万一实现了呢?~( ̄▽ ̄~)~

在这里插入图片描述


为什么选择码蹄集作为刷题软件?

码蹄集,是在全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC) 指导下建设的,其依托全国各大名校计算机系和清华大学出版社等单位的强大资源,旨在为计算机学习爱好者提供全面和权威的计算机习题。
.
在这里插入图片描述


目录

一、单链表

(一)、单链表的定义

参考代码

//单链表的定义
typedef struct LNode{                   //定义单链表结点类型int data;                           //每个节点存放一个数据元素struct LNode*next;                  //指针指向下一个节点
}LNode,*LinkList;
//增加一个新的结点:在内存中申请一个结点所需空间,并用指针p指向这个结点
LNode* p=(LNode*)malloc(sizeof(LNode));
//要表示一个单链表时,只需要声明一个头指针L,指向单链表的第一个结点
LinkList L; //声明一个指向单链表第一个结点的指针=LNode *L,但前者可读性更强

(二)、单链表的建立

//单链表的建立
//尾插法建立单链表
LinkList List_TailInsert(LinkList &L){      //正向建立单链表int x;                                  //设ElemType为整型L = (LinkList)malloc(sizeof(LNode));    //建立头结点,初始化空表LNode *s,*r=L;                          //r为表尾指针scanf("%d",&x);                  //输入9999表示结束while(x!=9999){s=(LNode *)malloc(sizeof(LNode));   //在r结点之后插入元素xs->data=x;r->next=s;r=s;                                //r指向新的表尾结构。永远保持r指向最后一个结点scanf("%d",&x);}r->next=NULL;                           //表尾指针置空return L;
}
//头插法建立单链表——重要应用:链表的逆置
LinkList List_HeadInsert(LinkList &L){      //逆向建立单链表LNode *s; int x;L=(LinkList)malloc(sizeof(LNode));      //创建头结点L->next=NULL;                           //初始为空链表scanf("%d",&x);                  //输入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;
}
//创建不带头结点的单链表
//初始化一个空的单链表
bool InitList(LinkList &L){L = NULL;                               //空表,暂时还没有任何结点(防止脏数据)return true;
}bool Empty(LinkList L){                     //判断单链表是否为空return (L==NULL);
}
/初始化一个单链表(带头结点)
bool InitListWithNode(LinkList &L){L = (LNode *) malloc(sizeof(LNode));    //分配一个头结点if(L==NULL)                             //内存不足,分配失败return false;L->next = NULL;                         //头结点之后暂时还没有节点return true;
}//判断单链表是否为空(带头结点)
bool EmptyWithNode(LinkList L){if(L->next==NULL)return true;elsereturn false;
}//------------------------------------------------
//带头结点,写代码更方便
//不带头结点,写代码更麻烦
// (1)对第一个数据节点和后续数据结点的处理需要用不同的代码逻辑
// (2)对空表和非空表的处理需要用不同的代码逻辑

(三)、单链表的插入删除

//插入
//按位序插入(带头结点)
//在第i个位置插入元素e(带头结点)
bool ListInsertWithNode(LinkList &L,int i,int e){if(i<1)return false;LNode *p;                               //指针p指向当前扫描到的结点int j=0;                                //当前p指向的是第几个结点p=L;                              //L指向头结点,头结点是第0个结点(不存数据)while(p!=NULL && j<i-1){                //循环找到第i-1个结点p=p->next;j++;}if(p==NULL)                             //i值不合法return false;LNode *s = (LNode *) malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;                            //将结点s连到p之后return true;                            //插入成功
} //平均时间复杂度O(n)
//按位序插入(不带头结点)
//插入、删除第1个元素时,需要改变头指针L
bool ListInsert(LinkList &L,int i,int e){if(i<1)return false;if(i==1){ //插入第1个结点的操作与其他结点操作不同LNode *s = (LNode *) malloc(sizeof(LNode));s->data = e;s->next = L;L = s;                              //头指针指向新结点return true;}LNode *p;                               //指针p指向当前扫描的结点int j=1;                                //当前p指向的是第几个结点p=L;                                    //p指向第1个结点(注意:不是头结点)while(p!=NULL && j<i-1){                //循环找到第i-1个结点p=p->next;j++;}                                       //自此往下,=return InsertNextNode(p,e);if(p==NULL)                             //i值不合法return false;LNode *s = (LNode *) malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return true;                            //插入成功
}
//指定结点的后插操作
//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p,int e){if(p==NULL)return false;LNode *s = (LNode *) malloc(sizeof(LNode));if(s==NULL)                             //内存分配失败return false;s->data = e;                            //用结点s保存数据元素es->next = p->next;p->next = s;                            //将结点s连到p之后return true;
} //时间复杂度O(1)
//指定结点的前插操作
//前插操作(法一):在p结点之前插入元素e
bool InsertPriorNode(LNode *p,int e){if(p==NULL)return false;LNode *s = (LNode *)malloc(sizeof(LNode));if(s==NULL)                             //内存分配失败return false;s->next=p->next;p->next=s;                              //新结点s连到p之后s->data=p->data;                        //将p中元素复制到s中p->data=e;                              //p中元素覆盖为ereturn true;
}//前插操作(法二):在p结点之前插入元素e
bool InsertPriorNode(LNode *p,LNode *s){if(p==NULL || s==NULL)return false;s->next=p->next;p->next=s;                              //新结点s连到p之后int temp = p->data;                     //交换数据域部分p->data=s->data;s->data=temp;return true;
}
//删除操作
//删除表L中第i个位置的元素,并用e返回删除元素的值//按位序删除(带头结点)
bool ListDeleteWithNode(LinkList &L,int i,int e){if(i<1)return false;LNode *p;                               //指针p指向当前扫描到的结点int j=0;                                //当前p指向的是第几个结点p=L;                                    //L指向头结点,头结点是第0个结点(不存数据)while(p!=NULL && j<i-1){                //循环找到第i-1个结点p=p->next;j++;}if(p==NULL)                             //i值不合法return false;if(p->next==NULL)                       //第i-1个结点之后已无其他结点return false;LNode *q=p->next;                       //令q指向被删除结点e = q->data;                            //用e返回元素的值p->next=q->next;                        //将*q结点从链中“断开”free(q);                                //释放结点的存储空间return true;
}
//删除指定结点p
bool DeleteNode(LNode *p){if(p==NULL)return false;LNode *q=p->next;                       //令q指向*p的后继结点p->data=p->next->data;                  //和后继结点交换数据域p->next=q->next;                        //将*q结点从链中“断开”free(q);                                //释放后继结点的存储空间return true;
}
//单链表的局限性:
// (1)无法逆向检索,有时候不太方便
// (2)如果p是最后一个结点,只能从表头开始依次寻找p的前驱,时间复杂度O(n)

(四)、单链表的查找

//查找
//按位查找,返回第i个元素(带头结点)
LNode *GetElemWithNode(LinkList L,int i){if(i<0)return NULL;LNode *p;                               //指针p指向当前扫描到的结点int j=0;                                //当前p指向的是第几个结点p=L;                                    //L指向头结点,头结点是第0个结点(不存数据)while(p!=NULL && j<i){                  //循环找到第i个结点p=p->next;j++;}return p;
} //平均时间复杂度O(n)//王道书版本:
LNode *GetElemWithNodeCS(LinkList L,int i){int j=1;LNode *p=L->next;if(i==0)return L;if(i<1)return NULL;while(p!=NULL && j<i){                  //循环找到第i个结点p=p->next;j++;}return p;
} //平均时间复杂度O(n)

//按值查找,找到数据域==e的结点
LNode * LocateElem(LinkList L,int e){LNode *p = L->next;int i=0;//从第1个结点开始查找数据域为e的结点while(p!=NULL && p->data !=e){p=p->next;i++;}return p;                               //找到后返回该结点指针,否则返回NULL
} //平均时间复杂度O(n)int LocateElemI(LinkList L,int e){LNode *p = L->next;int i=1;//从第1个结点开始查找数据域为e的结点while(p!=NULL && p->data !=e){p=p->next;i++;}if(p==NULL) return 0;else return i;                          //找到后返回该元素位置,如果没找到,则返回0
} //平均时间复杂度O(n)

二、主函数代码

//求表的长度
int Length(LinkList L){int len=0;                              //统计表长LNode *p = L;while(p->next != NULL){p = p->next;len++;}return len;
}//------------------------------------------------------------
void printListWithNode(LinkList L){         //带头结点LNode *p=L;p=p->next;while(p!=NULL){printf("%d ",p->data);p=p->next;}printf("\n");
}void printList(LinkList L){                  //不带头结点LNode *p=L;while(p!=NULL){printf("%d ",p->data);p=p->next;}printf("\n");
}int main(){LinkList L;                              //声明一个指向单链表的指针InitListWithNode(L);                  //初始化一个空表(带头结点)//InitList(L);                          //初始化一个空表(不带头结点)//插入ListInsertWithNode(L,1,3);      //带头结点ListInsertWithNode(L,2,4);ListInsertWithNode(L,3,5);printListWithNode(L);
//
//    if(ListInsert(L,1,3))                  //不带头结点
//        printList(L);//删除ListDeleteWithNode(L,2,5);printf("删除后的序列为:\n");printListWithNode(L);//查找LNode *p;p=GetElemWithNode(L,2);                         //按位查找printf("第2个元素值为:%d\n",p->data);int i = LocateElemI(L,4);                //按值查找if(i==0) printf("不存在该元素\n");else printf("元素4所在位置为:%d\n",i);//求单链表长度int len = Length(L);printf("该单链表的长度为:%d\n",len);return 0;
}

三、结语

感谢大家一直以来的不断支持与鼓励,码题集题库中的进阶塔350题正在逐步更新,之后会逐步跟进星耀,王者的题,尽请期待!!!
同时,也希望这些题能帮助到大家,一起进步,祝愿每一个算法道路上的“苦行僧”们,都能够历经磨难,终成正果,既然选择了这条路,走到了这里,中途放弃,岂不是太过可惜?

另附中国计算机学会的杰出会员、常务理事轩哥博士的B站视频讲解链接https://space.bilibili.com/518554541/?spm_id_from=333.999.0.0,供大家更好的进行学习与刷题~( ̄▽ ̄~)~

愿你的结局,配得上你一路的颠沛流离。
在这里插入图片描述

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

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

相关文章

com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The

配置文件示例: # SQL Server 数据源配置 spring.datasource.dynamic.datasource.sqlserver.urljdbc:sqlserver://100.100.0.0\\shili;databaseNamecs; spring.datasource.dynamic.datasource.sqlserver.usernamesa spring.datasource.dynamic.datasource.sqlserver.password sp…

数据结构第0章 初识

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 本篇笔记整理&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 0、思维导图1、数据结构1&#xff09;数据结构是什么&am…

LeetCode994腐烂的橘子(相关话题:矩阵dfs和bfs)

题目描述 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子&#xff1b;值 2 代表腐烂的橘子。 每分钟&#xff0c;腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。 返回 直到单…

获取Windows10系统原始安装日期

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 目标 获取Windows10系统最原始的安装日期&#xff1b;例如&#xff1a;刚买电脑时安装系统的时间。 步骤 第一步&#xff0c;请打开PowerShell&#xff0c;单击Windows P…

“推荐大战:抖音vs.快手”——背后的秘密全揭晓!

大家好&#xff0c;我是小米&#xff0c;一个热衷于技术分享的小伙伴。最近在面试的时候遇到了一个非常有趣的问题&#xff0c;也是很多人关心的话题——字节跳动产品面试题&#xff1a;说一下抖音和快手的推荐策略有什么不同&#xff1f;今天&#xff0c;就让我们一起来揭开这…

使用opencv+tesseract识别图片中的表格

描述 在java环境中使用opencv和tesserac识别一个图片表格 环境&#xff1a;opencv和tesseract安装在linux环境下&#xff0c;docker将运行springboot服务 opencv和tesseract的安装和docker加载可参考之前的文章 过程 将图片进行预处理&#xff0c;过滤掉颜色等干扰元素 提…

我的2023年度总结(一)

在本文开始之前&#xff0c;先对我2023年的所为进行一些道歉&#xff1a; 部分工作中的客户/合作伙伴&#xff0c;在2023年我可能时长怠慢了您的消息。但我真不是故意的(有时可能在忙其他事情)。2024年&#xff0c;如有任何问题请尽可能抛过来吧。部分粉丝朋友&#xff0c;甚至…

【Java开发岗面试】八股文—Java框架(Spring+SpringMVC+MyBatis+SpringBoot)

声明&#xff1a; 背景&#xff1a;本人为24届双非硕校招生&#xff0c;已经完整经历了一次秋招&#xff0c;拿到了三个offer。本专题旨在分享自己的一些Java开发岗面试经验&#xff08;主要是校招&#xff09;&#xff0c;包括我自己总结的八股文、算法、项目介绍、HR面和面试…

ctfshow 新手必刷菜狗杯 谜之栅栏题解记录

知识点&#xff1a;图片比较 拿到之后&#xff0c;有两个图片&#xff0c;直观看不出什么&#xff0c;尝试用工具比较。 用010editor打开其中一个&#xff0c;010editor的工具里面就有比较文件选项&#xff0c;比较两个文件&#xff0c;发现有一处不同。题目说栅栏&#xff0c…

基于时空的Ramsar湿地自动淹没映射利用Google Earth Engine

题目:Spatiotemporal‑based automated inundation mapping of Ramsar wetlands using Google Earth Engine 期刊:Scientific Reports 第一作者:Manish KumarGoyal 发表单位:University of Nebraska 发表日期:2023年 1. 摘要 研究背景:湿地是生态系统中最关键的组成…

如果你是这样选择项目的,那么再创业也不会成功的。2024新兴创业项目,2024普通人失业怎么创业

普通人怎么创业的&#xff1f;我昨天晚上吃饭的时候想了一个项目&#xff0c;觉得很可以&#xff0c;去干干怎么样&#xff1f;只能说死定了。没有任何数据支撑&#xff0c;想象出来的项目&#xff0c;它的成功率会非常低&#xff0c;因为在博概率&#xff0c;而且成功率不会超…

Avalonia学习(十五)-OxyPlot

今天开始继续Avalonia练习。展示一些样例&#xff0c;尤其是第三方库的使用。 本节&#xff1a;OxyPlot 1.引入OxyPlot.Avalonia 2.项目引入 在Main方法里增加OxyPlotModule.EnsureLoaded()方法调用。 public static void Main(string[] args) {OxyPlotModule.EnsureLoade…