【数据结构】堆和树详解堆和二叉树的实现堆的top-k问题

news2024/11/17 10:37:30

主页:醋溜马桶圈-CSDN博客

专栏:数据结构_醋溜马桶圈的博客-CSDN博客

gitee:mnxcc (mnxcc) - Gitee.com

目录

1.树概念及结构

1.1 树的概念

2.2 树的相关概念

1.3 树的表示

1.4 树在实际中的运用

2.二叉树的概念及结构

2.1 二叉树的概念

2.2 特殊的二叉树

​编辑2.3 二叉树的性质

2.4 二叉树的存储结构

2.5 二叉树的实现

3.堆的概念及结构

3.1 举例说明

3.2 堆(数据结构)与堆(内存)的区别

3.3 堆的意义 

3.4 堆的实现

3.4.1 堆向下调整算法

3.4.2 堆的创建 

3.4.2.1 创建

3.4.2.2 初始化

3.4.2.3 销毁

3.4.3 建堆时间复杂度

3.4.4 堆的插入

3.4.4.1 插入

3.4.4.2 向上调整

3.4.5 堆的删除

3.4.5.1 删除

3.4.5.2 向下调整

3.4.6 返回堆顶元素

3.4.7 判空

3.4.8 返回数据个数

3.4.9 访问

3.4.10 实现代码

3.4.10.1 Heap.h

3.4.10.2 Heap.c

3.5 堆的TOP-K问题

3.5.1 问题描述

3.5.2 算法思路

3.5.2.1 创建数据到文件中

3.5.2.2 并构建一个k个数的小堆

3.5.2.3 读取文件剩下的值

3.5.3 解决代码


1.树概念及结构

1.1 树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的

  • 有一个特殊的结点,称为根结点,根节点没有前驱结点
  • 除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  • 因此,树是递归定义

 注意:树形结构中,子树之间不能有交集,否则就不是树形结构

2.2 树的相关概念

  • 节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
  • 叶节点或终端节点度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点
  • 非终端节点或分支节点度不为0的节点; 如上图:D、E、F、G...等节点为分支节点
  • 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
  • 树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6
  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  • 树的高度或深度:树中节点的最大层次; 如上图:树的高度为4
  • 堂兄弟节点双亲在同一层的节点互为堂兄弟;如上图:H、I互为堂兄弟节点
  • 节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
  • 森林:由m(m>0)棵互不相交的树的集合称为森林;

1.3 树的表示

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既要保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等

我们这里就简单的了解其中最常用的孩子兄弟表示法

1.4 树在实际中的运用

(表示文件系统的目录树结构)

2.二叉树的概念及结构

2.1 二叉树的概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成

从上图可以看出:

  1. 二叉树不存在度大于2的结点
  2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

注意:对于任意的二叉树都是由以下几种情况复合而成的:

现实中的二叉树

2.2 特殊的二叉树

  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是2^k-1,则它就是满二叉树
    如果一个树是满二叉树,结点总数是N,那它的高度h=log2(N+1)
    每一层都是满的
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
    总结点数范围是:[2^(h-1),2^h-1]

    前h-1层是满的,最后一层不一定满,但是最后一层从左到右都是连续的

2.3 二叉树的性质

  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点.
  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数2^h-1
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有n0=n2+1
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度h= log2(n+1). (long2(n+1)是log以2为底,n+1为对数)
  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:

1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点

2. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子

3. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

2.4 二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构 

1. 顺序存储

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树

只有满二叉树或者完全二叉树才适合这种存储

父子节点间下标有一个规律关系:

  • leftchild = parent*2+1;
  • rightchild = parent*2+2;
  • parent = (child-1)/2;

2. 链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链。

 

2.5 二叉树的实现

二叉树链式结构的实现参考此文章:【数据结构】二叉树链式结构-CSDN博客

3.堆的概念及结构

堆的性质:  

  • 堆中某个节点的值总是不大于或不小于其父节点的值
  • 堆总是一棵完全二叉树

3.1 举例说明

堆一般是把数组数据看做是一棵完全二叉树

  • 小堆要求:任意一个父亲<=孩子
  • 大堆要求:任意一个父亲>=孩子 

比如:

我们分别分析一下:这个题选A

3.2 堆(数据结构)与堆(内存)的区别

我们数据结构中学的堆和C语言操作系统中学的堆不是一个东西,他们只是名字相同而已

  • 数据结构的堆是一棵特殊的完全二叉树
  • 操作系统的堆是一个内存区域的划分

3.3 堆的意义 

  • 堆排序  O(N*logN)
  • top k问题Top K算法分析_基于向量交集的topk搜索-CSDN博客
  • ...... 

3.4 堆的实现

3.4.1 堆向下调整算法

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆

向下调整算法有一个前提:左右子树必须是一个堆,才能调整

3.4.2 堆的创建 

下面我们给出一个数组

现在我们通过算法,把它构建成一个堆

一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆

3.4.2.1 创建

我们用一个动态顺序表来实现堆,创建一个结构体封装顺序表

3.4.2.2 初始化

3.4.2.3 销毁

3.4.3 建堆时间复杂度

3.4.4 堆的插入

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆

3.4.4.1 插入

这里我们以小堆为例,父亲节点小于儿子节点

以这棵树为例,

在逻辑结构上是一棵二叉树

而在物理结构上是顺序表(即数组)

如果我们分别插入10,20,30

3.4.4.2 向上调整

具体的流程如图

这里的算法思路是:插入到数组,如果child小于parent,则交换child和parent的值,child的坐标调整到parent,parent则调整到(parent-1)/2,继续进行比较交换,直到child调整到0位置结束,这就是向上调整的思路

向上调整的时间复杂度是O(logN)

3.4.5 堆的删除

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法

3.4.5.1 删除

删除我们规定删除堆顶的值,即删除根节点的值

要求删除根节点之后依然是一个堆

我们的思路是:

  1. 第一个节点和最后一个节点交换
  2. 尾删掉最后一个节点
  3. 然后从根节点开始向下调整

交换之后左右子树依旧是小堆

3.4.5.2 向下调整

向下调整算法的思路是:

  1. 找左右child节点
  2. 左右child节点比较
  3. 和较小的child节点交换
  4. 继续向下调整
  5. 调整到叶子节点就结束

向下调整的时间复杂度是O(logN)

具体的思路是:

找小节点:先找左节点,如果有右节点则比较左右节点,没有就直接是左节点

交换:如果child节点小于parent节点,则交换child和parent的值,然后parent走到child,child走到(parent*2+1)

如果走到叶子节点或者child大于parent节点就跳出循环

3.4.6 返回堆顶元素

3.4.7 判空

3.4.8 返回数据个数

3.4.9 访问

3.4.10 实现代码

 堆总是一棵完全二叉树

3.4.10.1 Heap.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;
//初始化
void HPInit(HP* php);
//销毁
void HPDestroy(HP* php);
//交换
void Swap(HPDataType* p1, HPDataType* p2);
//向上调整
void AdjustUp(HPDataType* a, int child);
//插入(小堆)
void HPPush(HP* php, HPDataType x);
//向下调整
void AdjustDown(HPDataType* a, int size, int parent);
//删除(根节点)
void HPPop(HP* php);
//返回堆顶数据
int HPTop(HP* php);
//判空
bool HPEmpty(HP* php);
//返回数据个数
int HPSize(HP* php);
3.4.10.2 Heap.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Heap.h"\
//初始化
void HPInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}
//销毁
void HPDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}
//交换
void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//向上调整
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}
//插入(小堆)
void HPPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;
	AdjustUp(php->a, php->size - 1);
}
//向下调整
void AdjustDown(HPDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		if ((child + 1) < size && a[child + 1] < a[child])
			child++;
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
//删除(根节点)
void HPPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	AdjustDown(php->a, php->size, 0);
}
//返回堆顶数据
int HPTop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}
//判空
bool HPEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}
//返回数据个数
int HPSize(HP* php)
{
	assert(php);
	return php->size;
}

3.5 堆的TOP-K问题

3.5.1 问题描述

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大

比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等

对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

1. 用数据集合中前K个元素来建堆

  • 前k个最大的元素,则建小堆
  • 前k个最小的元素,则建大堆

2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素

  • 将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素

3.5.2 算法思路

大致的实现代码是这样

数据量非常非常大的时候,比如在文件中有1000000000个值,找出最大的前十个

这时我们不可能建大堆去pop 10次,太消耗内存了

我们的思路是:假如TopK

  1. 创建数据到文件中
  2. 读取文件前k个值,构建一个k个数的小堆
  3. 读取文件剩下的值,与堆顶的数比较,如果比堆顶数值大,那就替换他,并向下调整
  4. 打印前k个数据 
3.5.2.1 创建数据到文件中

这里我们创建数据的时候%了10000000,保证数据都是在10000000以内的

我们创建的文件就在文件夹中

3.5.2.2 并构建一个k个数的小堆

3.5.2.3 读取文件剩下的值

3.5.3 解决代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = *p1;
}
void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}
void AdjustDown(int* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		if (child + 1 < size && a[child + 1] < a[child])
		{
			++child;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
void CreatNDate()
{
	//造数据
	int n = 10000000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		int x = (rand() + i) % 10000000;
		fprintf(fin, "%d\n", x);
	}
	fclose(fin);
}
void PrintTopK(const char* file, int k)
{
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen error");
		return;
	}
	//建一个k个数的小堆
	int* minheap = (int*)malloc(sizeof(int) * k);
	if (minheap == NULL)
	{
		perror("malloc fail");
		return;
	}
	//读取前k个数
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &minheap[i]);
		//建小堆
		AdjustUp(minheap, i);
	}
	//读文件剩下的值
	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF)
	{
		//与堆顶进行比较
		if (x > minheap[0])
		{
			//替代堆顶的值
			minheap[0] = x;
			//向下调整
			AdjustDown(minheap, k, 0);
		}
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", minheap[i]);
	}
	printf("\n");
	fclose(fout);
}
int main()
{

	//CreatNDate();
	PrintTopK("data.txt", 5);
	return 0;
}

结果我们就可以找出前k个值了

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

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

相关文章

手撕算法-长度最小的子数组

描述 分析 滑动窗口。窗口内的和大于等于tatger时&#xff0c;记录此时的长度&#xff0c;并比较是不是最小长度。窗口左边界右移&#xff0c;直到窗口内的和小于tatger。窗口内的和小于tatger时&#xff0c;窗口右边界右移。 代码 class Solution {public int minSubArray…

基于python+vue分类信息服务平台移动端的设计与实现flask-django-php-nodejs

分类信息服务平台是在Android操作系统下的应用平台。为防止出现兼容性及稳定性问题&#xff0c;框架选择的是django&#xff0c;Android与后台服务端之间的数据存储主要通过MySQL。用户在使用应用时产生的数据通过 python等语言传递给数据库。通过此方式促进分类信息服务平台信…

牛客NC108 最大正方形【中等 动态规划 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/0058c4092cec44c2975e38223f10470e 思路 动态规划: 先初始化第一行和第一列。然后其他单元格依赖自己的上边&#xff0c;左边和左上角参考答案Java import java.util.*;public class Solution {/*** 代码中的类…

【Linux】调试器-gdb的使用说明(调试器的配置,指令说明,调试过程说明)

目录 00.背景 01.安装 02.生成调试信息 03.调试过程 00.背景 在软件开发中&#xff0c;通常会为程序构建两种不同的版本&#xff1a;Debug模式和Release模式。它们之间的区别主要在于优化级别、调试信息、错误检查等方面&#xff1a; 1.Debug 模式&#xff1a; 优化级别低…

阿里云ECS服务器u1通用算力型CPU性能如何?

阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xff0c…

Gremlin查询语言用法示例

Gremlin 的基本用法 Gremlin Query Language 的基本用法主要包括构建图遍历的查询语句&#xff0c;这些语句由一系列的步骤组成&#xff0c;用于从图形中检索数据和修改数据。以下是一些基本用法的示例和解释&#xff1a; 选择所有顶点&#xff1a; 使用g.V()可以选择图中的所…

包叔推荐12代i3-独显组装电脑主机配置清单

去年Intel第十代i5-依然是主流热选机型。 今年&#xff0c;随着i3-的价格优势越来越大&#xff0c;已经成功取代了i5-。 今天包叔推荐几套12代i3-独立显卡组装电脑主机配置。 列表&#xff1a;一组核心显示配置&#xff0c;其余三组均为独立显示配置。 适合主机预算在2000元至3…

Spring Cloud Gateway教程

1 微服务网关概述 Spring Cloud Gateway是在 Spring 生态系统之上构建的API网关服务&#xff0c;旨在为微服务架构应用提供一种简单有效的统一的API路由管理方式。 Spring Cloud Gateway主要功能&#xff1a; 反向代理认证鉴权流量控制熔断日志监控 2 Spring Cloud Gateway三…

搭建一个简单的网络结构(Pytorch实现二分类)

搭建一个简单的网络结构&#xff08;Pytorch实现二分类&#xff09; 搭建一个神经网络并进行训练的话&#xff0c;大致需要分为三步&#xff1a; 第一步是数据的处理&#xff0c;将数据整理成输入网络结构中合适的格式第二步是网络的搭建&#xff0c;包括每层网络的结构和前向…

Neo4j桌面版导入CVS文件

之后会出来一个提示框&#xff0c;而且会跳出相关文件夹&#xff1a; 然后我们将CSV文件放在此目录下&#xff1a; 我们的relation.csv是这样的 参见&#xff1a; NEO4J的基本使用以及桌面版NEO4J Desktop导入CSV文件_neo4j desktop使用-CSDN博客

数学建模体育建模和经济建模国防科大版

目录 6.体育中的数学建模 7.经济学问题中的数学建模 7.1.实物交换模型 7.2.边际效应 7.3.最佳消费选择模型 6.体育中的数学建模 体育科学的研究中&#xff0c;也有大量的数学建模问题&#xff0c;例如&#xff1a;棒球的最佳击球点问题、滑板滑雪赛道的设计、越野自行车比…

基于springboot+vue的旅游推荐系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

全网最强JavaWeb笔记 | 万字长文爆肝JavaWeb开发——Web开发介绍

万字长文爆肝黑马程序员2023最新版JavaWeb教程。这套教程打破常规&#xff0c;不再局限于过时的老套JavaWeb技术&#xff0c;而是与时俱进&#xff0c;运用的都是企业中流行的前沿技术。笔者认真跟着这个教程&#xff0c;再一次认真学习一遍JavaWeb教程&#xff0c;温故而知新&…

利用免费 GPU 部署体验大型语言模型推理框架 vLLM

vLLM简介 vLLM 是一个快速且易于使用的 LLM&#xff08;大型语言模型&#xff09;推理和服务库。 vLLM 之所以快速&#xff0c;是因为&#xff1a; 最先进的服务吞吐量 通过 PagedAttention 高效管理注意力键和值内存 连续批处理传入请求 使用 CUDA/HIP 图快速模型执行 量…

输入N个整数,输出这个整数两两组合且不重复的所有二元组,要求从小到大输出并且用括号的形式。

输入描述: 第一行输入一个整数N&#xff0c;N<30。 第二行输入N个整数。 输出描述: 按题意输出。 输入样例#: 3 1 2 3 输出样例#: (1,2) (1,3) (2,1) (2,3) (3,1) (3,2) #include <stdio.h>void quicksort(int s[],int min,int max); //快速排序int partitio…

那些王道书里的题目-----计算机网络篇

注&#xff1a;仅记录个人认为有启发的题目 p155 34.下列四个地址块中&#xff0c;与地址块 172.16.166.192/26 不重叠&#xff0c;且与172.16.166.192/26聚合后的地址块不会引入多余地址的是&#xff08;&#xff09; A.172.16.166.192/27 B.172.16.166.128/26 …

53 initrd/initramfs 相关

前言 呵呵 这里主要是 探究一下 根文件系统 相关的东西 以及 附加了一些 系统启动的相关信息 计算机启动 硬件重置寄存器 设置初始化数据 计算机访问 0xffff0, 执行 bios 的代码, bios 选择启动设备, 然后执行 启动设备 boolloader 的代码 bootloader 将 boot.img 加载…

玩具蛇(蓝桥杯)

文章目录 玩具蛇题目描述答案&#xff1a;552dfs 玩具蛇 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝有一条玩具蛇&#xff0c;一共有 16 节&#xff0c;上面标着数字 1 至 16。每一节都是一个正方形的形…

GCC制作静态库详解

目录 前言 一.静态动态库区别 二.静态库制作 2.1 库文件命名 三.静态库文件制作 3.1 静态库制作 3.1.1 先获得.o文件 3.1.2 生成静态库文件 3.1.3 删除不必要文件 3.1.4 使用静态库 3.1.5 使用运行运行 前言 带大家快速入门&#xff0c;学会制作静态库。本文详细介绍在Linux系统…

“玩转文本魔法师:Python编程轻松变格式“

Hey小伙伴们&#xff0c;今天我们要一起打造一个文本转换器&#xff0c;就像神奇的魔法棒&#xff0c;能把普通的文字变成各种奇妙的格式&#xff01;想象一下&#xff0c;你的输入是&#xff1a;“Hello, World!”&#xff0c;输出可以是Markdown、HTML或者粗体、斜体的文字&a…