佛科院计算机软件技术基础——线性表

news2024/11/13 11:20:57

一、基础知识了解:

  1. 结构体的理解:

我们知道整型是由1位符号位和15位数值位组成,而就可以把结构体理解为我们定义的数据类型,如:

typedef struct
{
    int data[2];        //存储顺序表中的元素
    int len;                        //顺序表的表长
}SeqList;                             //顺序表类型

在这个结构体中我们定义前2*16位存放顺序表中的数据,最后1*16位存放表长

对于:

SeqList List;

这个就是类似于整型的一个结构体类型的变量,我们可以通过(List.len/List.data[i])调用结构体变量中的元素。

对于:

SeqList *L;//等同于int *L;,只不过可指向的数据类型不同

不过跟int *L;相同的,定义只是一个空指针,需要通过申请一段内存空间才能使用:

L=(SeqList*)malloc(sizeof(SeqList));
  1. 结构体变量的地址:

结构体变量的地址为首个成员的地址

  1. 指针的理解:

指针是一种通过指向地址来操纵数据的方式

如:

typedef struct
{
    //MAXSIZE是根据实际问题所定义的一个足够大的整数
    //datatype为顺序表中元素的类型,在具体实现中可为int、float、char类型或其他结构类型
    datatype data[MAXSIZE];        //存储顺序表中的元素
    int len;                        //顺序表的表长
}SeqList;                             //顺序表类型

//构造一个空表
SeqList *Init_SeqList()
{
    SeqList *L;//建立一个SeqList类型的空指针
    L=(SeqList*)malloc(sizeof(SeqList));//申请空间,并让L指向该空间的地址
    L->len=0; //顺序表的表长为0
    return L;
}
  1. 对SeqList **L的理解:

对于:

typedef struct node
{
    datatype data;            //data为结点的数据信息
    struct node *next;      //与SeqList *L;类似,存放了另一个LNode结构体变量的首地址
}LNode;                                  

我们可以重点看struct node *next; ,如果我们要操作next地址对应结构体的数据data,我们就要用到SeqList **L

如:

一、顺序表

  1. 顺序表定义:

typedef struct
{
    //datatype为表中元素类型(int,float等)
    //元素存放在data数组中
    //MAXSIZE是根据实际问题所定义的一个足够大的整数
    datatype data[MAXSISE];
    int len;//表长
}SeqList;
  1. 指向顺序表的指针变量

SeqList list,*L;
//list是结构体变量,它内部含有一个可存储顺序表的data数组
//L是指向List这类结构体变量的指针变量

其中:

(1)List.data[i]或L->data[i]均表示顺序表中第i个元素的值

(2)List.len或L->len均表示顺序表的表长

(3)“L=(SeqList*)malloc(sizeof(SeqList));”表示生成一个顺序表存储空间

  1. 顺序表的初始化

typdefine struct 
{
    datatype data[MAXSIZE];
    int len;
}Seqlist;
Seqlist *seqlist_Init()
{
    Seqlist *l;
    l = (Seqlist*)malloc(sizeof(Seqlist));
    l->len = 0;
    return l;
}
  1. 建立顺序表:(没搞懂)

(1)头部插入

先读取需要输入数据个数,再进行读取外部数据操作,最后将数据按顺序存放到顺序表中的数组

void CreatList(SeqList **L)
{
    int i, n;
    printf("Input length of List: ");
        scanf("%d", &n);
    printf("Input elements of List: \n");
    for(i=1;i<=n;i++)
        scanf("%d", &(*L)->data[i]);
        (*L)->len=n;
}

(2)尾部插入

LNode *CreateLinkList()
{
   LNode *head, *p, *q; 
   char x;
   head=(LNode*)malloc(sizeof(LNode));       //生成头结点
   head->next=NULL;
   p=head; q=p;                                    //指针q始终指向链尾结点
   printf("Input any char string: \n");
   scanf("%c", &x);
   while(x!='\n')                                  //生成链表的其他结点
   {
      p=(LNode*)malloc(sizeof(LNode));
      p->data=x;
      p->next=NULL;
      q->next=p;                                    //在链尾插入
      q=p;
      scanf("%c", &x);
   }
   return head;                                   //返回单链表表头指针
}
  1. 插入运算:

先判断表是否满了和插入位置是否合理,再将i到len个从后面到前面逐个向后移,最后再插入到第i个位置

void Insert_SeqList(SeqList *L, int i, datatype x)
{
    int j;
    if(L->len==MAXSIZE-1)                   //表满
        printf("The List is full!\n");
    else
        if(i<1|| i>L->len+1)                //插入位置非法
            printf("The position is invalid !\n");
        else
        {
            for(j=L->len;j>=i;j--)          //将an~ai顺序后移一个元素位置
                L->data[j+1]=L->data[j];
            L->data[i]=x;                   //插入x到第i个位置
            L->len++;                          //表长增1
        }
}}

  1. 删除运算:

void Del_LinkList(LNode *head , int i)
{                     //删除单链表head上的第i个数据结点
   LNode *p, *q;
   p=Get_LinkList(head, i-1);               //查找第i-1个结点
   if(p==NULL)
   printf("第i-1个结点不存在!\n "); 
                                       //待删结点的前一个结点不存在,无待删结点
   else
      if(p->next==NULL)
         printf("第i个结点不存在!\n");        //待删结点不存在
      else
      {
         q=p->next;                //q指向第i个结点
         p->next=q->next;            //从链表中删除第i个结点
         free(q);                //系统回收第i个结点的存储空间
      }
}
  1. 查找:

给值查找存储位置:以该一位元素是否为x和该位是否在在顺序表中为判断条件,最后如果跳出时的元素为x则返回i,不是则返回0

int Location_SeqList(SeqList *L, datatype x)
{
    int i=1;                                  //从第一个元素开始查找
    while(i<L->len&&L->data[i]!=x)
    //顺序表未查完且当前元素不是要找的元素
        i++;
    if(L->data[i]==x)
        return i;                                //找到则返回其位置值
    else
        return 0;                                              //未找到则返回0值
}

二、单链表

  1. 单链表结点定义:

只需要定义一个存放数据和后一个节点地址的结构体就行


typedef struct node
{
    datatype data;            //data为结点的数据信息
    struct node *next;      //next为指向后继结点的指针
}LNode;                                  //单链表结点类型
  1. 建立单链表:

首先建立一个任意的头节点,读取外部输入数据,

void CreateLinkList(LNode **head)
{                       //将主调函数中指向待生成单链表的指针地址(如&p)传给**head
    char x;
    LNode *p;
    *head=(LNode *)malloc(sizeof(LNode)); //在主调函数空间生成链表头结点
    (*head)->next=NULL;        //*head为链表头指针
    printf("Input any char string: \n");
    scanf("%c", &x);      //结点的数据域为char型,读入结点数据
    while(x!='\n')             //生成链表的其他结点
    {
        p=(LNode *)malloc(sizeof(LNode));     //申请一个结点空间
        p->data=x;
        p->next=(*head)->next;       //将头结点的next值赋给新结点*p的next
        (*head)->next=p;    //头结点的next指针指向新结点*p实现在表头插入
        scanf("%c", &x);            //继续生成下一个新结点
    }

(1)为什么使用LNode **head?(未解决)

由于我们要与主函数联系起来,必须确定头节点的

  1. 查找:

(1)按序号:

根据指针域一直寻址到第i个结点,以循环次数与最后一个节点为结束标志

LNode *Get_LinkList(LNode *head, int i)
{                                 //在单链表head中查找第i个结点
   LNode *p=head;              //由第一个结点开始查找
   int j=0;
   while(p!=NULL&&j<i)         //当未查到链尾且j小于i时继续查找
   {
      p=p->next;
      j++;
   }
   return p;           //找到则返回指向i结点的指针值,找不到则p返回空值
}

(2)按值查找:

根据指针域一直寻址,以找到目标值和最后一个数为结束标志

LNode *Locate_LinkList(LNode *head, char x)
{                                //在单链表中查找结点值为x的结点
    LNode *p=head->next;     //由第一个数据结点开始查找
    while(p!=NULL&&p->data!=x) 
                                 //当未查到链尾且当前结点不等于x时继续查找
        p=p->next;
    return p; 
        //找到则返回指向值为x的结点的指针值,找不到则p返回空值
}
  1. 求表长:

从第一个结点寻址到最后一个结点,并做计数

int Length_LinkList(LNode *head)
{
    LNode *p=head;                //p指向单链表头结点
    int i=0;                         //i为结点计数器
    while(p->next!=NULL)
    {
        p=p->next;
        i++;
    }
    return i;                       //返回表长值i
}
  1. 插入:

利用查找函数获得第i-1个结点的地址,如果该结点地址为空(即最后一个结点),说明插入操作非法;如果不为空,创建一个新节点数据域存放插入数据,指针域域存放下一个结点的地址,上一个结点的指针域放新节点的地址

void Insert_LinkList(LNode *head, int i, char x)
{                                               //在单链表head的第i个位置上插入值为x的元素
   LNode *p, *q;
   p=Get_LinkList(head, i-1);            //查找第i-1个结点*/
   if(p==NULL) 
      printf("Error ! \n");                 //第i-1个位置不存在而无法插入
   else
   {
      q=(LNode *)malloc(sizeof(LNode));    //申请结点空间
      q->data=x;
      q->next=p->next;                      //完成插入操作①
      p->next=q;                             //完成插入操作②
   }
}
  1. 删除:

首先像插入操作一样判断删除操作是否非法,如果合法,则让第i-1个结点的地址域直接存放第i+1个结点的地址,同时把第i个结点的空间释放

算法如下:
void Del_LinkList(LNode *head , int i)
{                     //删除单链表head上的第i个数据结点
   LNode *p, *q;
   p=Get_LinkList(head, i-1);               //查找第i-1个结点
   if(p==NULL)
   printf("第i-1个结点不存在!\n "); 
                                       //待删结点的前一个结点不存在,无待删结点
   else
      if(p->next==NULL)
         printf("第i个结点不存在!\n");        //待删结点不存在
      else
      {
         q=p->next;                //q指向第i个结点
         p->next=q->next;            //从链表中删除第i个结点
         free(q);                //系统回收第i个结点的存储空间
      }
}

三、循环链表

  1. 查找循环链表中某个数:

与单链表类似,只不过最后的一个查找的地址不是NULL而是头节点

LNode *Locate_CycLink(LNode *head, datatype x)
{
    LNode *p=head->next;       //由第一个数据结点开始查
    while(p!=head&&p->data!=x)//未查完循环链表且当前结点不等于x时继续查找
    p=p->next;
    if(p!=head)                       //head   代表结束点
        return p;              //找到值等于x的结点*p,返回其指针值p
    else
        return NULL; //当p又查到头结点时则无等于x值的结点,故返回NULL值
}

四、单链表应用

例1:

通过两个指针将

void Convert(LNode *H)
{
   LNode *p, *q;
   p=H->next;               //p指向剩余结点链表的第一个数据结点
   H->next=NULL;               //新链表H初始为空
   while(p!=NULL)
   {
     q=p;                   //从剩余结点链表中取出第一个结点
     p=p->next;             //p继续指向剩余结点链表新的第一个数据结点
     q->next=H->next;     //将取出的结点*q插入新链表H的链首
     H->next=q;
   }
}

例2:

首先把A的头节点赋给C,释放B的头节点,再将A、B中较小的用头插法赋给C,再该链表推进到下一个结点,循环该操作直到A,B中任意一方到最后一个结点,最后将剩余元素用头插法赋给C

 void Merge(LNode *A, LNode *B, LNode **C)
{                           //将增序链表A、B合并成降序链表*C
    LNode *p, *q, *s;
    p=A->next;              //p始终指向链表A的第一个未比较的数据结点
    q=B->next;               //q始终指向链表B的第一个未比较的数据结点
    *C=A;                     //生成链表的*C的头结点
    (*C)->next=NULL;
    free(B);                 //回收链表B的头结点空间
    while(p!=NULL&&q!=NULL)
    {   //将A、B两链表中当前比较结点中值小者赋给*s
        if(p->data<q->data)
        {
            s=p;   p=p->next;
        }
        else
        {
            s=q; q=q->next;
        }
        s->next=(*C)->next; //用头插法将结点*s插到链表*C的头结点之后
        (*C)->next=s;
    }
    if(p==NULL)    //如果指向链表A的指针*p为空,则使*p指向链表B
        p=q;
    while(p!=NULL)
    {//将*p所指链表中的剩余结点依次摘下插入链表*C的链首
        s=p;p=p->next;
        s->next=(*C)->next;   (*C)->next=s;
    }

例3:

首先建立一个单链表,再将最后一个地址域赋上头节点地址形成循环列表,

void Josephus(int n, int m, int k)
{
   LNode *p, *q;
   int i;
   p=(LNode*)malloc(sizeof(LNode));
   q=p;
    for(i=1;i<n;i++)     //从编号k开始建立一个单链表
   {
      q->data=k;
      k=k%n+1;
      q->next=(LNode*)malloc(sizeof(LNode));
      q=q->next;
   }
   q->data=k; q->next=p;              //链接成循环单链表,此时p指向编号为k的结点
   while(p->next!=p)       //当循环单链表中的结点个数不为1时
   {
      for(i=1;i<m;i++)
      {
         q=p;  p=p->next;
      }                          //p指向报数为m的结点,q指向报数为m-1的结点
      q->next=p->next;              //删除报数为m的结点
      printf("%4d", p->data);       //输出出圈人的编号
      free(p);                      //释放被删结点的空间
      p=q->next;                    //p指向新的开始报数结点
   }
   printf("%4d", p->data);         //输出最后出圈人的编号
}

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

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

相关文章

Python识别二维码的两种方法(cv2)

在学习Python处理二维码的过程中&#xff0c;我们看到的大多是“用python生成酷炫二维码”、“用Python制作动图二维码”之类的文章。而关于使用Python批量识别二维码的教程&#xff0c;并不多见。所以今天我会给大家分享两种批量识别二维码的Python技巧&#xff01;pyzbar PI…

【架构师】零基础到精通——服务与网关

博客昵称&#xff1a;架构师Cool 最喜欢的座右铭&#xff1a;一以贯之的努力&#xff0c;不得懈怠的人生。 作者简介&#xff1a;一名Coder&#xff0c;软件设计师/鸿蒙高级工程师认证&#xff0c;在备战高级架构师/系统分析师&#xff0c;欢迎关注小弟&#xff01; 博主小留言…

IV测试系统3A太阳能模拟器在光伏中应用

一、概述IV测试系统3A太阳能模拟器应具备光束准直、光斑均匀、辐照稳定、且与太阳光谱匹配的特点&#xff0c;使用户可足不出户的完成需要太阳光照条件的测试。科迎法电气提供多规格高品质的太阳模拟器&#xff0c;可适用于单晶硅、多晶硅、非晶硅、染料敏化、有机、钙钛矿等各…

织梦TXT批量导入TAG标签并自动匹配相关文章插件

织梦TXT批量导入TAG标签并自动匹配相关文章插件是一种非常有用的插件&#xff0c;它可以帮助网站管理员快速地将TAG标签添加到文章中&#xff0c;并自动匹配相关文章。 以下是该织梦TXT批量导入TAG标签插件的几个优点&#xff1a; 1、提高网站的SEO效果&#xff1a;TAG标签是搜…

如何利用ReconPal将自然语言处理技术应用于信息安全

关于ReconPal 网络侦查一直是网络安全研究以及渗透测试活动中最重要的阶段之一&#xff0c;而这一阶段看起来很容易&#xff0c;但往往需要很大的努力和很强的技术才能做好来。首先&#xff0c;我们需要使用正确的工具、正确的查询/语法以及正确的操作&#xff0c;并将所有信息…

服务拆分及远程调用

目录 服务拆分 服务拆分注意事项 服务间调用 步骤一&#xff1a;注册RestTemplate 步骤二&#xff1a;修改业务层代码 总结&#xff1a; 提供者和消费者 思考 服务调用关系 服务拆分 服务拆分注意事项 单一职责&#xff1a;不同微服务&#xff0c;不要重复开发相同业…

备战英语6级——记录复习进度

开始记录—— 学习&#xff1a;如何记录笔记&#xff1f; 1&#xff1a;首先我认为&#xff1a;电脑打字比较适合我&#xff01; 2&#xff1a;先记笔记&#xff0c;再“填笔记”&#xff01; 记笔记就是一个框架&#xff0c;记录一个大概的东西。后面需要在笔记中&#xff0…

WEB前端性能(页面+接口)

WEB前端性能&#xff08;页面接口&#xff09;前端性能渲染过程Blocked时间Connect时间Send时间Waiting时间TTFBReceive时间响应时间OS相关指标idleiowaitussyswapmemory前端性能渲染过程 Blocked时间 是浏览器查看本地有没有缓存的资源&#xff0c;不会与服务器进行交互&…

自动化测试 ——自动卸载软件

在平常的测试工作中&#xff0c;经常要安装软件&#xff0c;卸载软件, 即繁琐又累。 安装和卸载完全可以做成自动化。 安装软件我们可以通过自动化框架&#xff0c;自动点击Next,来自动安装。 卸载软件我们可以通过msiexec命令行工具自动化卸载软件 用msiexec 命令来卸载软件 …

Linux系列 常用命令(目录和文件管理)vi和vim 编辑使用,(笔记)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.常用命令&#xff08;目录和文件管理&#xff09; 1.查看文件内容 2.统计…

【Java开发】JUC基础 03:线程五大状态和主要方法

1 概念介绍&#x1f4cc; 五大状态&#xff1a;new&#xff1a;Thread t new Thread(); 线程对象一旦被创建就进入到了新生状态&#xff1b;就绪状态&#xff1a;当调用start()方法&#xff0c;线程立即进入就绪状态&#xff0c;但不意味着立即调度执行&#xff1b;运行状态&a…

【蓝桥杯集训10】Tire树 字典树 最大异或对专题(3 / 3)

目录 字典树模板 1、插入操作 2、查询操作 143. 最大异或对 - trie 二进制 3485. 最大异或和 - 前缀和Trie滑动窗口 字典树模板 活动 - AcWing 字典树&#xff1a;高效存储和查找字符串集合的数据结构 son[节点1地址][值]节点2地址 —— 节点1的子节点为节点2cnt[节点地…

第三十八章 linux-并发解决方法二(信号量)

第三十八章 linux-并发解决方法二&#xff08;信号量&#xff09; 文章目录第三十八章 linux-并发解决方法二&#xff08;信号量&#xff09;信号量的定义DOWN操作UP操作相对于自旋锁&#xff0c;信号量的最大特点是允许调用它的线程进入睡眠状态这意味着试图获得某一信号的进程…

第六章.决策树(Decision Tree)—ID3算法,C4.5算法

第六章.决策树(Decision Tree) 6.1 ID3算法,C4.5算法 1.决策树适用的数据类型 比较适合分析离散数据&#xff0c;如果是连续数据要先转换成离散数据再做分析 2.信息熵 1).概念&#xff1a; 一条信息的信息量大小和它的不确定性有直接的关系&#xff0c;要搞清楚一件非常不确…

动态规划(以背包问题为例)

1) 要求达到的目标为装入的背包的总价值最大&#xff0c;并且重量不超出2) 要求装入的物品不能重复动态规划(Dynamic Programming)算法的核心思想是&#xff1a;将大问题划分为小问题进行解决&#xff0c;从而一步步获取最优解的处理算法。动态规划算法与分治算法类似&#xff…

JAVA线程池原理详解二

JAVA线程池原理详解二 一. Executor框架 Eexecutor作为灵活且强大的异步执行框架&#xff0c;其支持多种不同类型的任务执行策略&#xff0c;提供了一种标准的方法将任务的提交过程和执行过程解耦开发&#xff0c;基于生产者-消费者模式&#xff0c;其提交任务的线程相当于生…

Linux操作系统安装MySQL(rpm安装)

Linux操作系统安装MySQL&#xff08;rpm安装&#xff09;1 背景2 环境说明3 准备工作3.1 端口查看3.2 检查安装3.3 创建MySQL用户和组4 MySQL安装4.1 下载MySQL4.2 解压安装包4.3 安装MySQL4.4 初始化MySQL4.5 启动MySQL4.6 设置MySQL初始密码4.6.1 查看数据库初始密码4.6.2 更…

力扣-合作过至少三次的演员和导演

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;1050. 合作过至少三次的演员和导演二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运…

taobao.user.openuid.getbyorder( 根据订单获取买家openuid )

&#xffe5;免费不需用户授权 根据订单获取买家openuid&#xff0c;最大查询30个 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 请求示例 TaobaoClient client new DefaultTaobaoClient(url, appkey, secret); UserOpenuidGetbyorderR…

性能测试流程及基本介绍

性能名次解释 1、用1个用户&#xff08;几乎毫无压力&#xff09;访问服务器&#xff0c;观察项目的基本性能 2、单场景&#xff08;单接口-基准测试&#xff09; 目的1&#xff1a;最大处理能力 压力测试 关注结果 目的2&#xff1a;评估接口的性能 负载测试 关注过程 一点点…