【数据结构笔记13】

news2024/10/3 17:59:17

408数据结构答题规范

原视频
视频参考,以下为视频的笔记

  1. 需要写的部分
    在这里插入图片描述
    如果题目要求了函数名、参数列表、返回值类型就按题目的来

在这里插入图片描述

  1. 函数的类型可以是返回值类型或者void类型,如果函数名不清楚里面的功能是什么,在函数title下面最好写一行注释说明函数的功能
    在这里插入图片描述

输入和输出

print函数+注释
在这里插入图片描述

结构体和类

struct node{
	int value;
	node *next;
	node(int value, node *next):value(value),next(next){}
};

在这里插入图片描述

动态内存分配

参考链接

C程序使用malloc、realloc等内存申请函数在堆上分配和释放内存的。
用malloc和realloc函数申请的空间不能被系统自动释放,因此,即使这些空间在程序中已经不用,别的程序也不能用。所以C中提供了一个专门的函数free(地址)来释放这些空间。例如free(ptr);,就释放了ptr指向的空间。为防止出现野指针,最好再加上ptr=NULL。

如果发现用malloc申请的空间不够使用或者多了,可以利用realloc函数来调整空间大小。realloc的函数原型为:

void *realloc(void *ptr, size_t size);

第一个参数ptr是重新申请空间的首地址,size是字节数。即从ptr这个地址开始重新申请大小为size字节的空间。用realloc重新申请的空间并不损害原来空间上已存放的数据。

这个函数一般用于调整malloc申请的空间大小,所以ptr一般就设定为malloc函数返回的地址,然后,size设定为更大或更小的数。例如,原来已经使用malloc申请了能存k个int型数据的空间,由于数据量的增加,这个空间不够,可以用p=(int *)realloc(p,sizeof(int)*(k+n));对空间进行扩展,此时,空间就可以存放k+n个int型数据,值得注意的是realloc得到的内存空间可能不是malloc原申请的空间(原来空间的值可能被释放了),因此,“p=”不能丢。
有了realloc函数,就可以不用先确定非常大的空间,而是先申请少量的空间,等空间不够时,再用realloc来增加。

#include <stdio.h>
int main() {
int *p;
p=(int *)malloc(sizeof(int)*10);
printf("Previous address=%ld\n",p);
for(int i=0;i<=9;i++)
  p[i]=i+1;
p=(int *)realloc(p,sizeof(int)*(10+10));//重新分配空间,p=不能丢,realloc得到的空间起始地址可能不是原先申请的空间起始地址
printf("Current address=%ld\n",p);
for(int j=9;j<=19;j++)
   p[j]=j+1;
free(p);  //释放空间
p=NULL;//防止野指针
return 0;
}
  1. 申请辅助数组
  2. 申请链表

① 申请辅助数组

int n=10;
int *a = (int *)malloc(n*sizeof(int))//数组
int *b = (int *)malloc(sizeof(int))//单个

free(a);
free(b);
int n = 10;
int *a = new int[n];
int *b = new int;

delete []a;
delete b;

②链表动态申请内存

//创建动态链表
#include<stdio.h>
#include<stdlib.h>
typedef struct student{
	int num;//数据域
	float score;
	struct student *next;//地址域
}Student;
struct student *head = 0,*p1,*p2;
int tempnum,tempnum1;
float tempscore,tempscore1;
tempnum = 202022020;
tempscore = 98.5;
//第一个节点
head  = p1=p2 = (struct student*) malloc(sizeof(struct student));
if(NULL==p1)return 0;
p1->num = tempnum;
p1->score = tempscore;
p1->next=0;

free(p1);//释放p1指向的空间
p1=NULL;
return 0;
               

head = p1=p2 = (struct student*) malloc(sizeof(struct student));
在这里插入图片描述

C语言中,直到C99标准出现之前,声明数组时在方括号内只能使用整数常量表达式。而C99做了很大改进,允许数组的中的值是整形变量或是整形表达式,这就解释了下面的情况:

int n;
scanf ("%d". &n);
int array[n];

虽然n确实是需要运行时动态确定的变量,但是在C99中,以这种变量作为数组大小的形式已经是允许的了。这样的数组就被称之为“变长数组"。
注意:变长数组是指用整型变量或表达式声明或定义的数组,而不是说数组的长度会随时变化,变长数组在其生存期内的长度同样是周定的。

可变长数组(变量开数组)

在这里插入图片描述

可以直接使用的函数

min函数 返回a、b中的较小值
max函数 返回a、b中的较大值
swap函数 交换a、b的值
abs函数 返回a的绝对值

可以使用的c++库函数

在这里插入图片描述
可以使用c++的stack和queue
关于vector和array存在争议,不推荐使用
不可以使用list,priority,queue,map,set等等这些
不可以使用sort和qsort等排序相关的函数,排序算法要求自己实现。

memset函数作用

void *memset(void *s, int ch, size_t n);

函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 [1]

  1. 第一:memset函数按字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。

  2. memset(void *s, int ch,size_t n);中ch实际范围应该在0~~255,因为该函数只能取ch的后八位赋值给你所输入的范围的每个字节,比如int a[5]赋值memset(a,-1,sizeof(int )*5)memset(a,511,sizeof(int )*5) 所赋值的结果是一样的都为-1;因为-1的二进制码为(11111111 11111111 11111111 11111111)而511的二进制码为(00000000 00000000 00000001 11111111)后八位都为(11111111),所以数组中每个字节,如a[0]含四个字节都被赋值为(11111111),其结果为a[0](11111111 11111111 11111111 11111111),即a[0]=-1,因此无论ch多大只有后八位二进制有效,而后八位二进制的范围在(0~255)中改。而对字符数组操作时则取后八位赋值给字符数组,其八位值作为ASCII码。

  3. 第三: 搞反了 ch 和 n 的位置.
    一定要记住如果要把一个char a[20]清零,一定是 memset(a,0,20*sizeof(char));
    而不是 memset(a,20*sizeof(char),0);

  4. 第四: 过度使用memset.

char buffer[4];
memset(buffer,0,sizeof(char)*4);
strcpy(buffer,"123");
//"123"中最后隐藏的'\0'占一位,总长4位。

以下情况并不多余,因某些编译器分配空间时,内存中默认值并不为0:

char buffer[20];
memset(buffer,0,sizeof(char)*20);
memcpy(buffer,"123",3);
//这一条的memset并不多余,memcpy并没把buffer全部覆盖,如果没有memset,
//用printf打印buffer会有乱码甚至会出现段错误。
//如果此处是strcpy(buffer,"123");便不用memset,
//strcpy虽然不会覆盖buffer但是会拷贝字符串结束符

2015 41

用单链表保存m个整数,结点的结构为: ,且|data|<n(n为正整数)。现要求设计一个时间复杂度尽可能高效的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。例如,若给定的单链表head如下:
在这里插入图片描述
则删除节点后的head为:
在这里插入图片描述
要点:
(1)给出算法的基本设计思想。
(2)使用C或C++语言,给出单链表结点的数据类型定义。
(3)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
(4)说明你所设计算法的时间复杂度和空间复杂度。

(1)算法的基本思想:
算法的核心思想是用空间换时间。使用辅助数组记录链表中已出现的数值,从而只需对链表进行一趟扫描。
因为|data|≤n,故辅助数组temp的大小至少为n+1,各元素的初值均0。
依次扫描链表中的各结点,同时检查temp[|data|]的值,如果为0,则保留该结点,并令++temp[|data|];否则,将该结点从链表中删除。
(2)使用C语言描述的单链表结点的数据类型定义

# 链表结点定义
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
typedef struct ListNode{
int data;
struct Node *pNext;
}NODE,*PNODE;
## 筛选链表中绝对值重复的元素
void FiltrateRep(PNODE L,int len)
{
	int temp[len];
	memset(temp,0,sizeof(int)*len);
	PNODE pre,p;
	pre=L;
	while(pre->pNext!=NULL){
		p=pre->pNext;
		if(p!=NULL){
			if(temp[abs(p->data)]<1){
				++temp[abs(p->data)];
				pre = p;
			}else{
				pre->pNext = p->pNext;
				free(p);
			}
		}

	}
}


本算法的时间空间复杂度都为O(n)

删除排序链表的重复元素|

我们从指针 cur 指向链表的头节点,随后开始对链表进行遍历。如果当前 cur 与 cur.next 对应的元素相同,那么我们就将 cur.next 从链表中移除;否则说明链表中已经不存在其它与 cur 对应的元素相同的节点,因此可以将 cur 指向 cur.next。


class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) {
            return head;
        }

        ListNode* cur = head;
        while (cur->next) {
            if (cur->val == cur->next->val) {
                cur->next = cur->next->next;
            }
            else {
                cur = cur->next;
            }
        }

        return head;
    }
};

删除排序链表的重复元素||

具体地,我们从指针 cur 指向链表的哑节点,随后开始对链表进行遍历。如果当前 cur.next 与 cur.next.next 对应的元素相同,那么我们就需要将 cur.next 以及所有后面拥有相同元素值的链表节点全部删除。我们记下这个元素值 x,随后不断将 cur.next 从链表中移除,直到 cur.next 为空节点或者其元素值不等于 x 为止。此时,我们将链表中所有元素值为 x 的节点全部删除。

如果当前 cur.next 与 cur.next.next 对应的元素不相同,那么说明链表中只有一个元素值为 cur.next 的节点,那么我们就可以将 cur 指向 cur.next。

当遍历完整个链表之后,我们返回链表的的哑节点的下一个节点 dummy.next 即可。


class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) {
            return head;
        }
        
        ListNode* dummy = new ListNode(0, head);

        ListNode* cur = dummy;
        while (cur->next && cur->next->next) {
            if (cur->next->val == cur->next->next->val) {
                int x = cur->next->val;
                while (cur->next && cur->next->val == x) {
                    cur->next = cur->next->next;
                }
            }
            else {
                cur = cur->next;
            }
        }

        return dummy->next;
    }
};


复杂链表的复制

给定链表的头节点 head ,复制普通链表很简单,只需遍历链表,每轮建立新节点 + 构建前驱节点 pre 和当前节点 node 的引用指向即可。
本题链表的节点新增了 random 指针,指向链表中的 任意节点 或者 nullnull 。这个 random 指针意味着在复制过程中,除了构建前驱节点和当前节点的引用指向 pre.next ,还要构建前驱节点和其随机节点的引用指向 pre.random 。 本题难点: 在复制链表的过程中构建新链表各节点的 random 引用指向。

哈希表
利用哈希表的查询特点,考虑构建 原链表节点 和 新链表对应节点 的键值对映射关系,再遍历构建新链表各节点的 next 和 random 引用指向即可。
在这里插入图片描述


Node* copyRandomList(Node* head){
	//判断链表是否为空
	if(head==NULL)return NULL;
	//建立map容器
	Node *cur = head;
	unordered_map<Node*,Node*> map;
	//复制各节点,并建立“原节点->新节点”的Map映射
	while(cur!=NULL){
		map[cur] = new Node(cur->val);
		cur = cur ->next;
	}
	cur=head;
	//构建新链表的next和random指向
	while(cur!=NULL){
		map[cur]->next = map[cur->next];
		map[cur]->random = map[cur->random];
		cur = cur->next;
	}
	//返回新链表的头节点
	return map[head];
}

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

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

相关文章

磁盘存储和文件系统管理【1.9】

磁盘存储和文件系统管理【1.9】 12、磁盘存储和文件系统12.1.管理存储12.1.1.新加10G硬盘并识别12.1.2.备份查看MBR分区表二进制信息12.1.3.删除破坏分区表12.1.4.恢复MBR分区表12.1.5.完整步骤12.1.6.fdisk分区12.1.7.gdisk分区12.2.文件系统12.2.1.查看支持的文件系统格式12.…

音视频入门基础:FLV专题(11)——FFmpeg源码中,解析SCRIPTDATASTRING类型的ScriptDataValue的实现

一、引言 从《音视频入门基础&#xff1a;FLV专题&#xff08;9&#xff09;——Script Tag简介》中可以知道&#xff0c;根据《video_file_format_spec_v10_1.pdf》第80到81页&#xff0c;SCRIPTDATAVALUE类型由一个8位&#xff08;1字节&#xff09;的Type和一个ScriptDataV…

Java类的生命周期-连接阶段

Java类的生命周期-连接阶段 上篇讲述了类的加载阶段&#xff0c;通过类加载器读取字节码文件后在方法区与堆区生成对应的存放类信息的对象&#xff0c;本篇将讲解他的下一阶段-连接阶段 上篇说到类加载的五大阶段&#xff1a; #mermaid-svg-6YmaEnIO4rCKbIZg {font-family:&quo…

Cpp::STL—vector类的模拟实现(11)

文章目录 前言一、各函数接口总览二、默认成员函数vector();vector(size_t n, const T& val T( ));template< class InputIterator> vector(InputIterator first, InputIterator last);vector(const vector<T>& v);vector<T>& operator(const v…

腾讯云SDK基本概念

本文旨在介绍您在使用音视频终端 SDK&#xff08;腾讯云视立方&#xff09;产品过程中可能会涉及到的基本概念。 音视频终端 SDK&#xff08;腾讯云视立方&#xff09; 应用 音视频终端 SDK&#xff08;腾讯云视立方&#xff09;通过应用的形式来管理您的项目&#xff08;Ap…

C/C++进阶(一)--内存管理

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; 学习专栏C语言_Stark、的博客-CSDN博客 其它专栏&#xff1a; 数据结构与算法_Stark、的博客-CSDN博客 ​​​​​​项目实战C系列_Stark、的博客-CSDN博客 座右铭&a…

免费录屏软件工具:助力高效屏幕录制

录屏已经成为了一项非常实用且广泛应用的技术。无论是制作教学视频、记录游戏精彩瞬间&#xff0c;还是进行软件操作演示等&#xff0c;我们都常常需要一款可靠的录屏软件。今天&#xff0c;就让我们一起来探索那些功能强大录屏软件免费版&#xff0c;看看它们是如何满足我们多…

ARTS Week 42

Algorithm 本周的算法题为 2283. 判断一个数的数字计数是否等于数位的值 给你一个下标从 0 开始长度为 n 的字符串 num &#xff0c;它只包含数字。 如果对于 每个 0 < i < n 的下标 i &#xff0c;都满足数位 i 在 num 中出现了 num[i]次&#xff0c;那么请你返回 true …

【数据结构强化】应用题打卡

应用题打卡 数组的应用 对称矩阵的压缩存储 注意&#xff1a; 1. 2.上三角的行优先存储及下三角的列优先存储与数组的下表对应 上/下三角矩阵的压缩存储 注意&#xff1a; 上/下三角压缩存储是将0元素统一压缩存储&#xff0c;而不是将对角线元素统一压缩存储 三对角矩阵的…

接口隔离原则在前端的应用

什么是接口隔离 接口隔离原则&#xff08;ISP&#xff09;是面向对象编程中的SOLID原则之一&#xff0c;它专注于设计接口。强调在设计接口时&#xff0c;应该确保一个类不必实现它不需要的方法。换句话说&#xff0c;接口应该尽可能地小&#xff0c;只包含一个类需要的方法&am…

SKD4(note上)

微软提供了图形的界面API&#xff0c;叫GDI 如果你想画某个窗口&#xff0c;你必须拿到此窗口的HDC #include <windows.h> #include<tchar.h> #include <stdio.h> #include <strsafe.h> #include <string>/*鼠标消息 * 键盘消息 * Onkeydown * …

实验 3 存储器实验

实验 3 存储器实验 1、实验目的 掌握静态随机存储器 RAM 的工作特性。掌握静态随机存储器 RAM 的读写方法。 2、实验要求 (1)做好实验预习&#xff0c;熟悉MEMORY6116 芯片各引脚的功能和连接方式&#xff0c;熟悉其他实验元器件的功能特性和使用方法&#xff0c;看懂电路图…

CSS | 响应式布局之媒体查询(media-query)详解

media type(媒体类型)是CSS 2中的一个非常有用的属性&#xff0c;通过media type我们可以对不同的设备指定特定的样式&#xff0c;从而实现更丰富的界面。media query(媒体查询)是对media type的一种增强&#xff0c;是CSS 3的重要内容之一。随着移动互联网的发展&#xff0c;m…

中国靠谱热门交友软件app排行榜前十名测评

在信息飞速发展的时代&#xff0c;交友软件层出不穷。究竟哪些才是靠谱又热门的呢&#xff1f;这份交友软件 app 排行榜将为你揭晓&#xff0c;带你走进不同的社交天地&#xff0c;开启精彩交友之旅。 咕哇找搭子小程序&#xff1a;这是一个实名制的找搭子交友平台&#xff0c;…

基于ssm的学生社团管理系统 社团分配系统 社团活动调度平台 学生社团管理 信息化社团管理开发项目 社团活动管理 社团预约系统(源码+文档+定制)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

时尚科技融合:Spring Boot下的“衣依”服装销售平台

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…

虚拟机三种网络模式详解

在电脑里开一台虚拟机&#xff0c;是再常见不过的操作了。无论是用虚拟机玩只有旧版本系统能运行的游戏&#xff0c;还是用来学习Linux、跑跑应用程序都是很好的。而这其中&#xff0c;虚拟机网络是绝对绕不过去的。本篇文章通俗易懂的介绍了常见的虚拟网络提供的三种网络链接模…

小红书AI配音神器:3秒变声百种风格

小红书AI配音神器&#xff1a;3秒变声百种风格 小红书推出黑科技FireRedTTS&#x1f3a4;&#xff0c;3秒克隆你的声音✨&#xff0c;支持搞怪、温柔等多种风格&#x1f389;&#xff01;只需几秒参考音频&#xff0c;轻松生成个性化语音&#xff0c;短视频配音神器&#x1f3…

把白底照片变蓝色用什么软件免费 批量更换证件照底色怎么弄

作为专业的修图师&#xff0c;有时候也会接手证件照修图和换底色工作&#xff0c;这种情况下&#xff0c;需要换底色的照片也许达到上百张。为了提高工作效率&#xff0c;一般需要批量快速修图&#xff0c;那么使用什么软件工具能够给各式不同的照片批量更换背景色呢&#xff1…

Python并发编程(1)——Python并发编程的几种实现方式

更多精彩内容&#xff0c;请关注同名公众&#xff1a;一点sir&#xff08;alittle-sir&#xff09; Python 并发编程是指在 Python 中编写能够同时执行多个任务的程序。并发编程在任何一门语言当中都是比较难的&#xff0c;因为会涉及各种各样的问题&#xff0c;在Python当中也…