408强化(二)线性表纯享版

news2024/9/20 18:53:50

目录

一、顺序表(数组)和链表总览

二、考情分析

 2.1 从历年考情可以看出,如果一个方法出现了第2次,一般是以下情况:

 2.2 没有考过的地方

三、 共同操作或考法

3.1 多指针后移

3.2 逆置

3.3 空间换时间的操作

3.4 只保留首次出现的元素(共同考法)

3.4 排序

 四、独有操作或考法

4.1 在顺序表中遍历,找到符合要求的元素并删除

4.2 判断单链表是否存在环

4.3 找到两个链表中的共同结点


红色字体为线性表的共同操作, 蓝色背景为下文有模板。绿色字体为统计的考频分析(易想到不饶弯子的)

一、顺序表(数组)和链表总览

第一步:看到题目,分析情况

  1. 多指针后移                    2010较优解; 2020年最优解(三指针)
  2. 以空间换时间                2018
  3. 排序或排序后利于操作 2013较优解; 2016暴力解
  4. 逆置                              2010最优解(三次逆置)
  5. 折半查找                       2011最优解
  6. 删除、插入
  7. 只保留首次出现的元素

第二步:分析坑 

  1. 表长是奇数或偶数时需讨论
  2. 空表怎么处理

 第一步:看到题目,分析情况

  1. 多指针后移
  2. 以空间换时间     2015
  3. 排序
  4. 头插法逆置         2019 
  5. 前后指针            2012最优解
  6. 快慢指针
  7. 只保留首次出现的元素

第二步:分析坑

  1. 头插法是逆序建立链表,尾插法是正序建立链表
  2. 单链表只能向后查找,故可能需要前驱指针
  3. 不可修改链表结构
  4. 有free()操作
  5. 需malloc()结点 
  6. 注意是否有头结点
  7. 不同于数组改变下标,链表是p=p->next,本质一样

二、考情分析

2.1 从历年考情可以看出,如果一个方法出现了第2次,一般是以下情况:

  1. 升级版。2011年能用二指针后移,2020年需要设置三指针后移。
  2. 数组考过,换到链表考。如2015年和2018年都是以空间换时间
  3. 太过重要。如快排,是某一年的解的一部分。2013年是较优解,2016年是暴力解。

 2.2 没有考过的地方

数组的插入删除;链表的多指针后移;不使用数组进行链表排序。都具有很大的考察可能。

2021,2022,2023年为图,二叉树,图。2018,2019,2020年都是线性表,2024年很可能回归线性表。

三、 共同操作或考法

3.1多指针后移

条件:多个线性表;有序。

  1. 归并链表或数组,使之有序。
  2. 归并的升级操作:找到两个序列中的相同元素或其他,本质仍是比大小,改变的是比的内容或对结果的操作。

多指针后移常用于有序线性表(顺序表和链表都可以),如果考试中给出有序的线性表,优先考虑这种方式,这种方式可以用于合并多个有序线性表、查找共同排序后第k个大小的元素等等,归并排序就是用到了这种思想。

归并两个升序数组

                       
void Merge(int A[], n, B[], m){  //数组A、B长度分别为n、m
  int C[n+m]; //新数组
   int pa=pb=k=0;                  //pa、pb作为遍历A、B的下标
   while (pa<n && pb<m)              //直到有一个数组遍历完
      if (A[pa]<B[pb])                //将小的那个数存入C数组
         C[k++]=A[pa++];
      else C[k++]=B[pb++];
   for (; pa<n; i++)
      C[k++]=A[pa];                  //将A中剩余的数存入C数组
   for (; pb<m; j++)
      C[k++]=B[pb];                  //将B中剩余的数存入C数组
}

归并两个升序链表,结果存放在LA中,使之降序。

void MergeList (LinkList &La,LinkList &Lb){
LNode *pa=La->next,*pb=Lb->next; //分别是工作指针
LNode *r;//头插法防止断链需要的指针
La->next=NULL; //结果链表初始化为空
while(pa!=NULL&&pb!=NULL)
if(pa->data<=pb->data){
r=pa->next; //r暂存pa的后继指针
pa->next=La->next;
La->next=pa;
pa=r; //恢复pa为当前待比较结点
}
else{
r=pb->next; //r暂存pb的后继指针
pb->next=La->next;
La->next=pb;
pb=r; //恢复pb为当前待比较结点
}
if(pa!=NULL) pb=pa  //pa不空的将原La剩余元素继续前插进结果链表La,这里用到了一个小技巧
while(pb!=NULL){ //pb不空的话将Lb剩余元素继续前插进结果链表La
r=pb->next; 
pb->next=La->next;
La->next=pb;
pb=r;
}
free(Lb); //将最后只剩下的一个Lb头结点free掉
}

归并两个升序链表,结果存放在LA中,使之升序

void Merge(LinkList *La, *Lb){           
   LNode *pa=La->next, *pb=Lb->next;    //pa、pb指向L1、L2第一个元素
   LNode *r=La;                      //新链表头节点为La,r指向末尾
   LNode *par, *pbr;                    //用来暂存pa->next和pb->next
   while (pa!=null && pb!=null)         //直到有一个链表遍历完
      if (pa->data<pb->data){            //将小的那个数存入新链
          par=p->next;                    //par为pa下一个元素
          r->next=pa;                    //pa插入到r后面
          pa->next=NULL;                //这是新链最后一个元素
          r=pa;                           //尾指针r指向最后一个元素
          pa=par;                          //pa指向pa下一个元素
      }
      else{ 
          pbr=pb->next;                  //pbr为pb下一个元素
          r->next=pb;                   //pb插入到r后面
          pb->next=NULL;               //这是新链最后一个元素
          r=pb;                          //尾指针r指向最后一个元素
          pb=pbr;                         //pb指向pb下一个元素
      }
   if (pa!=null)
      r->next=pa;                      //将剩余部分连到r后面
   if (pb!=null)
      r->next=pb;                      //将剩余部分连到r后面
   //La是合并后的升序链表,注意最后此时r已经不是指向新链表尾元素的指针了

3.2逆置

顺序表

数组可以任意下标到任意下表逆置

void Reverse(int low,int high,Sqlist *L){

ElemType temp;  //用于暂存

for(int i=0;i<(high-low+1)/2;i++){

//注意边界条件,交换对应位置元素

temp=L.data[low];

L.data[low]=L.data[high];

L.data[high]=temp;}

}

链表

链表用头插法逆置

LinkList Reverse(LinkList L){

LNode *p,*r;
//p为工作指针,r为p的后继结点指针

p=L->next;

L->next=NULL;      //先断开头结点

while(p!=NULL){    

r=p->next;

p->next=L->next;  L->next=p;   //将p结点插入到头结点后,第一个结点插入时即为尾结点

p=r;                       //工作指针后移

}

return L;

}

3.3 空间换时间的操作

空间保存状态。原序列最多只有n种情况,设置一个大小为n,初始值为0的数组A[n-1]用于保存这些情况。遍历一遍序列将出现的情况对于的数组置1。

3.4 只保留首次出现的元素(共同考法)

顺序表课后第06题

链表课后第12题

 3.4 排序

传统数组排序

快速排序的平均时间复杂度是O(nlogn),平均空间复杂度是O(logn),是考试中最快的不稳定排序算法,一般要用到排序时都使用快速排序。快速排序的最坏时间复杂度是O(n2),最坏空间复杂度都是O(n),但我们只需要加一个小优化就能避免最坏情况:即随机选择一个元素作为枢值。优化后最坏时间复杂度O(nlogn),最坏空间复杂度O(logn)。
(注:快速排序有很多写法,交换式和挖坑式,不同写法中间过程不一样但只要能实现排序即可,本代码适用于算法大题,方便记忆)
代码如下:

 void Qsort(int A[], L, R){           //a数组保存数据,L和R是边界
   if (L>=R) return;              //当前区间元素个数<=1则退出
   int pivot, i=L, j=R;             //i和j是左右两个数组下标移动
   把A[L~R]中随机一个元素和A[L]交换   //快排优化,使得基准值的选取随机
   pivot=A[L];                     //pivot作为基准值参与比较
   while (i<j){
      while (i<j && A[j]>pivot)
          j--;
      while (i<j && A[i]<=pivot)
          i++;R
      if (i<j)
          swap(A[i], A[j]);       //交换A[i]和A[j]
   }
   swap(A[L], A[i]); //将基准值放入他的最终位置
/*此时A[L~i-1]<=A[i]<=A[i+1~R]*/
   Qsort(A, L, i-1);          //递归处理左区间
   Qsort(A, i+1, R);           //递归处理右区间
      }

单链表排序

  1. 使用O(n)大小的辅助数组,进而可以使用第7章的排序算法,最后重置链表的结点数据域。
  2. 直接插入排序思想,代码如下:
void   Sort(LinkList &L){

LNode *p=L->next,*pre;

LNode *r=p->next;

p->next=NULL;   //构造只含一个数据结点的有序表

p=r;

while(p!=NULL){  //每次插入一个结点并使链表有序

r=p->next;

pre=L;  //将pre置于头结点,用于循环找到插入的合适位置

while(pre->next!=NULL&&pre->next->data<p->data)  pre=pre->next;

p->next=pre->next; pre->next=p; //将*p插入到*pre之后

p=r; //工作指针迭代

}//第一个while

}//void

 四、独有操作或考法

4.1 在顺序表中遍历,找到符合要求的元素并删除

两种方法

  1. 用count记录已保存的元素个数,遍历时将需要保存的元素移动到下标count的位置,更新count值
  2. 用count记录已删除的元素个数,遍历时更新count,或者将需要保留的元素前移count

两种方法结束后都要修改L.length

  1. L.length=count;
  2. L.length-=count;

4.2 判断单链表是否存在环

如果有环,快指针早晚追上慢指针

课后21题

4.3 找到两个链表中的共同结点

1)对齐后(前后指针),同时扫描两链表

2)for循环枚举


 咸鱼学长统计,我在这里保存一下方便查看

 

 

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

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

相关文章

一分钟了解微信公众号服务器配置自动回复

1、建一个web服务工程 2、开放任意一个接口&#xff0c; 比如 /aaa/bbb/ccc 把接口路径配置在这里&#xff0c;ip为公网ip或域名&#xff0c;其他的参数默认&#xff0c;对入门选手没啥用 3、该接口允许get和post两种方式访问&#xff0c;接口需要对于访问方式编写两套逻辑…

ubuntu下如何使用wireshark抓包,保姆级教程

Wireshark&#xff08;前称Ethereal&#xff09;是一个网络封包分析软件。网络封包分析软件的功能是截取网络封包&#xff0c;并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口&#xff0c;直接与网卡进行数据报文交换。 一、安装wireshark 打开终端&…

教育行业如何高效使用知识库?

在线知识库的有效性在商业世界中是众所周知的。知识库通常用于客户支持&#xff0c;或管理员工的内部知识。在教育系统中&#xff0c;知识库的优势鲜为人知。知识库是可用于各种应用程序的多功能软件。特别是考虑到当前网络影响我们所有人生活的环境&#xff0c;教育越来越多地…

数据结构<堆>

&#x1f387;&#x1f387;&#x1f387;作者&#xff1a; 小鱼不会骑车 &#x1f386;&#x1f386;&#x1f386;专栏&#xff1a; 《数据结构》 &#x1f393;&#x1f393;&#x1f393;个人简介&#xff1a; 一名专科大一在读的小比特&#xff0c;努力学习编程是我唯一…

字符串匹配 - 模式预处理:朴素算法(Naive)(暴力破解)

朴素的字符串匹配算法又称为暴力匹配算法&#xff08;Brute Force Algorithm&#xff09;&#xff0c;最为简单的字符串匹配算法。算法简介朴素的字符串匹配算法又称为暴力匹配算法&#xff08;Brute Force Algorithm&#xff09;&#xff0c;它的主要特点是&#xff1a;没有预…

功率放大器科普知识(晶体管功率放大器的注意事项)

虽然功率放大器是电子实验室的常用仪器&#xff0c;但是很多人对于它却没有清晰的认识&#xff0c;下面就让安泰电子来为大家介绍功率放大器的科普内容以及使用注意事项&#xff0c;希望大家可以对功率放大器有清晰的认识。功率放大器可以把输入信号的功率放大&#xff0c;以满…

NFT Insider #86:A16z 领投,YGG 获得 1380 万美元融资,The Sandbox与《北斗神拳》合作

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据&#xff0c;艺术新闻类&#xff0c;游戏新闻类&#xff0c;虚拟世界类&#…

智能小车红外循迹原理

循迹电路循迹电路由收发一体的红外收发管P1&#xff0c;P2&#xff1b;电位器R18&#xff0c;R29&#xff1b;发光二极管D6&#xff0c;D7和芯片LM324等组成。一共有两路&#xff0c;对应的红外电位器用于调节灵敏度。LM234用于信号的比较&#xff0c;并产生比较结果输出给单片…

MySQL8.0 optimizer_switch变化

Optimizer_switch变量是支持对优化器行为的控制。是一组值标志&#xff0c;每个标志都有一个on或off的值&#xff0c;以指示是否启用或禁用相应的行为。 MySQL8.0里除了熟悉的hash join重大变化之外&#xff0c;其他方面也有优化。 mysql> SHOW VARIABLES LIKE OPTIMIZER_…

14 基数排序(桶排序)

文章目录1 基数排序基本思想2 基数排序的代码实现2.1 java2.2 scala3 基数排序总结1 基数排序基本思想 1) 基数排序&#xff08;radix sort&#xff09;属于“分配式排序”&#xff08;distribution sort&#xff09;&#xff0c;又称“桶子法”&#xff08;bucket sort&#…

【Python】循环语句(while,for)、运算符、字符串格式化

一、while循环Python 编程中 while 语句用于循环执行程序&#xff0c;即在某条件下&#xff0c;循环执行某段程序&#xff0c;以处理需要重复处理的相同任务。其基本形式为&#xff1a;while 判断条件(condition)&#xff1a;执行语句(statements)执行语句可以是单个语句或语句…

Git、小乌龟、Gitee的概述与安装应用超详细(组长与组员多人开发版本)

目录 一、概述 1.什么是Git&#xff1f; 2.Git历史来源 3.Git的优点? 4.什么是版本控制&#xff1f; 5.版本控制工具种类&#xff1f; 6.Git工作机制 7.Git、小乌龟、Gitee、凭据管理器的简单介绍 二、Git下载安装 下载Git 安装Git 安装完成后查看版本 三、下载小…

防水蓝牙耳机评测,值得入手的四款蓝牙耳机分享

提到蓝牙耳机&#xff0c;大家第一反应是音质跟佩戴舒适度要好&#xff0c;其实除了这两个功能&#xff0c;还有就是防水性能不能少&#xff0c;而且防水等级越高&#xff0c;耳机寿命也就越长&#xff0c;那么&#xff0c;我们该如何 选购一款好用的蓝牙耳机呢&#xff1f;下面…

Echarts 配置横轴竖轴指示线,更换颜色、线型和大小

第018个点击查看专栏目录本示例是描述如何在Echarts上配置横轴竖轴指示线&#xff0c;更换颜色、线型和大小。方法很简单&#xff0c;参考示例源代码。 文章目录示例效果示例源代码&#xff08;共85行&#xff09;相关资料参考专栏介绍示例效果 示例源代码&#xff08;共85行&a…

数据的TCP分段和IP分片

本文简述下TCP分段和IP分片的区别与联系。 我们知道&#xff0c;用户空间的数据拷贝到内核空间的TCP发送缓冲区&#xff08;这个是一个结构体&#xff0c;叫sk_buffer&#xff0c;简称skb&#xff09;后就由内核网络协议栈做后续的封装和发送处理了&#xff0c;用户无需考虑下…

【Node.js】开发自己的包!

造包开发自己的包&#xff01;初始化包的基本结构页面使用根据需要也可以将模块化拆分编写包的说明文档发布包把包发布在npm上删除已发布的包模块的加载机制内置模块的加载机制自定义模块的加载机制第三方模块的加载机制当目录作为模块时的加载机制开发自己的包&#xff01; 初…

3|射频识别技术|第二讲:RFID系统的组成与工作原理|批注·上

https://blog.csdn.net/m0_57656758/article/details/128153964?spm1001.2014.3001.5501我国用无线射频识别技术实现药品管理的市场还是空白其运用具有较大的市场空间。药品运输及存储环境监控药品有效期监控提升用药安全策略血液制剂监控特殊、违禁药品监控商品价格监控药品生…

【Flutter】入门Dart语言:简单易懂的变量指南

文章目录一、概述二、详解1. 变量的声明2. 常量变量3.late 延迟初始化变量4. 变量的命名规则三、总结一、概述 “不抱有希望的人生是毫无意义的。” —— 阿卜杜勒阿齐兹 Dart中的变量是存储值的容器。它们可以是数字、字符串、布尔值或其他数据类型。变量在定义时必须指定类型…

网络原理 (1)

网络原理 文章目录1. 前言&#xff1a; 2. 应用层2.1 XML2.2 json2.3 protobuffer3. 传输层3.1 UDP3.1 TCP4. TCP 内部的工作机制 &#xff08;重点&#xff09;1. 确认应答 2.超时重传3. 连接管理3.1 建立联系 &#xff1a;三次握手3.2 断开连接 : 四次挥手4. 滑动窗口5. 流量…

长按power键,点击重启按钮,系统重启流程一

1.有可能会涉及到如下文件 2.文件流程