[数据结构]栈
栈的基本概念
数据结构的三要素 – 逻辑结构、数据运算、存储结构 。(存储结构存储结构不同,运算的实现方式不同。)
栈 (Stack)是只允许在一端进行插入或删除操作的线性表。即栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。
栈顶(Top):线性表允许插入删除的那一端。
栈底(Bottom):固定的,不允许进行插入和删除的一端。
空栈:不包含任何元素的栈。
栈道操作特性:后进先出(Last In First Out,LIFO)。
栈的数学性质: $n$个不同元素进栈,出栈元素不同排列的个数为$\frac1{n+1}C^n_{2n}$。上述公式称为卡特兰(Catalan)数,可采用数学归纳法证明。
栈道基本操作:
InitStack(&S):初始化栈。构造一个空栈S,分配内存空间。
DestroyStack(&S):销毁栈,并释放栈S所占用的内存空间。
Push(&S, x):进栈,若栈S未满,则将x加入使之成为新栈顶。
Pop(&S, &x):出栈,若栈S非空,则弹出栈顶元素,并将x返回。
GetTop(S, &x):读取栈顶元素。若栈S非空,则用x返回栈顶元素。
StackEmpty(S):判断栈S是否为空。若S为空,则返回true,否则返回false
顺序栈的定义12345#define MaxSize ...
全平台科学上网教程
b58f97dd19d7688fb3b7739465734ef8f7bf1f7785a4de40f7d6f40df4006b8725d16a443a4664f1e9db919a69e1ec16830a47bed730e3db4bb9a229a7e255eec9c1b4b79149b8958b049986e5e11d427ecc831411219929cc64a0cf80002de75ca0856dfa2b2430dcecc20a6d8792255babd0e0ec3385a319652f1c3d141492de332bf4a00fc2acc602033321fbab91f26364fbb110b2d2b4be3dc64c9866cfaa7272b6282fd47722dd5c594194e0b3080bcc5c025d32437fa6923e7ddac41e88dd762ec51aac39ccfadaa32c57b0311bbd4ab04b6113f6d355d04e801bce6733fa6c87751588600b6c9b1ec6e75e01592d271012b8527cbc0884bf446e340c4f51111557de34eba980fd0c17a6405a6d945edd69d4b420e528ea5fccbb19f8859a1a9ddc3e4c43a31d0 ...
[数据结构]顺序表和链表的比较
顺序表和链表的比较0x01 存取/读写方式顺序表可以顺序存取,也可以随机存取,只需要访问一次。时间复杂度:$O(1)$
链表只能从头顺序读取元素。时间复杂度:$O(n)$
0x02 逻辑结构和物理结构顺序表采用顺序结构,逻辑上相邻的元素,对应的物理存储位置也相邻。
链表采用链式结构,逻辑结构上相邻的元素,物理位置不一定不一定相邻,对应的逻辑关系是用指针来表示的。
0x03 CRUD操作顺序表对于按值查找,顺序表无序时时间复杂度:$O(n)$,有序时可用折半/二分查找,时间复杂度:$O(log_2n)$;
对于按位查找,顺序表支持随机存取,时间复杂度为:$O(1)$;
链表对于按值查找,链表的时间复杂度为:$O(n)$;
对于按位查找,链表的时间复杂度也为:$O(n)$;
由于顺序表在物理结构上也是连续存放的,在进行插入和删除操作时需要挪动大量数据,造成执行效率低下。
所以在大量数据的情况下适合使用链表进行存储。
0x04 空间分配 顺序存储在静态存储分配情形下,一旦存储空间装满就不能扩充,若再加入新元素,则会出现内存溢出,因此需要预先分配足够大的存储空间。预先分配过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。动态存储分配虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且若内存中没有更大块的连续存储空间,则会导致分配失败。链式 ...
[花椒生存]进入服务器萌新教程
花椒生存萌新教程
服务器地址:mc.q1jun.cn
服务器交流群: 912457864
服务器语音: https://kaihei.co/V0aEIh
0x01 安装我的世界
如果你已经安装了我的世界(Java)1.18.1版本则可以跳过这步。
0x0101 配置Java 17环境我的世界1.18.1版本是在Java 17环境下运行的,如Java 16、Java 8等都不能运行。
查看Java版本的方法:
Win+R输入cmd,打开命令行界面输入:
1java -version
回车,若显示如下:
123java version "17.0.1" 2021-10-19 LTSJava(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
则说明是Java 17.0.1,恭喜你,可以运行1.18.1版本!
如果不是Java 17,则需要重新安装Java环境,或者通过其他MC启动器辅助安装(略,参考搜索引擎)。
Java 17下载地址:https://www.oracle.com/java/technologies/downloads/#jdk17- ...
Java接口实现插入和冒泡排序
Java接口实现插入和冒泡排序0x01 要求对整型数组排序的静态方法代码如下:
class SortedInts {
public static void newsort(int[] numbers, SortMethod s) {
s.sort(numbers);
for (int n : numbers) {
System.out.printf(“%d “, n);
}
System.out.println();
}
}
其中SortMethod是一个接口,请定义该接口,并定义2个类InsertSort和BubbleSort实现该接口,分别在这两个实现类中使用直接插入排序和冒泡排序实现 sort 方法。
对数组 a 进行直接插入排序的算法如下:
for (int i = 1; i < a.length; i++) {
int key = a[i];
int j = i - 1;
while (j >= 0 && a[j] > key) {
a[j+1] = a[j];
j–;
}
a[j+1] = key;
}
对数组 a 进行 ...
Java 实现分数的相加相乘化简
Java 实现分数的相加相乘化简0x01 要求:设计一个表示分数的类Fraction。这个类用两个int类型的变量分别表示分子和分母。这个类的构造方法是:
Fraction(int a, int b) 构造一个a/b的分数。
这个类要提供以下的功能:
double toDouble(); 将分数转换为double
Fraction plus(Fraction r);
将自身和r的分数相加,产生一个新的Fraction的对象。注意小学五年级学过两个分数如何相加。
Fraction multiply(Fraction r);
将自身和r的分数相乘,产生一个新的Fraction的对象。
void print();
将自身以“分子/分母”的形式输出到标准输出,并带有回车换行。
需要考虑以下情况:
当分母为0时,显示“错误,分母不能为0”。
当分子为0时,显示0
当分母为1时,直接显示分子
分数为负数时,负号显示在最前面
分数显示为最简形式。如2/4应该被约分为1/2。
类 Fraction 中可以用以下方法进行约分和调整负号
12345678910111213141516171819 private void yuefen() { int aa = (int) Math.abs(a); int ...
如何用Python爬取B站可爱的表情包
如何用Python爬取B站可爱的表情包0x01 前言最近在逛B站的时候发现了一套我寻找已久的猫人表情包:
但是当我点进去之后,看到了灰色的下载按钮逐渐起了杀心
简单来说,就是不让你下载,只能下载这个必剪APP才能使用,无奈这个剪辑软件并不适配MacOS系统!可恶
但是这并不影响我下载,只要按下正义的F12,选择元素,找到链接,然后右键保存:
点击这个直接链接之后右键就能下载到本地:
But!,这样虽然可以下载了,但是每个表情都要点进去按F12,一共有228张表情,岂不是要重复228次?
那我们只好写一个正义的爬虫来帮我下载了。
0x02 思路1由于这个网站是动态加载的,我们需要做更多的操作。
利用selenium和BeautifulSoup4来模拟浏览器操作,获取该页面所有我们需要的数据
123from selenium.webdriver.common.keys import Keys #模仿键盘,操作下拉框的from bs4 import BeautifulSoup #解析html的from selenium import webdriver #模仿浏览器的
我使用的是Chrome浏览器,需要去下载selenium所需要的对应的浏览器驱动,下载地址如下:https://chromedriver.chromium.org/downloads
我使用的Chr ...
0512实训作业
0x01 登入模块代码实现
创建User实体类
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748package ruanko.newspublish.entity;public class Users { private int uid; private String username; private String password; public Users(){} public Users(int uid, String username, String password) { this.uid = uid; this.username = username; this.password = password; } public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } public String getUsernam ...
系统重装保姆级教程
系统重装保姆级教程
写给还不会装机的人: 对于没有接触过系统重装的人来说,装系统是一个很高端很难的事情。事实上,装机真的简单到不得了,我们只是把前人的劳动成果照搬而已,所有装机用到的东西,都不是我们自己创作的,我们只是学会如何用而已。
因为硬盘分区表格式的不同,以及其他各种原因,如果不去设置,Win7只能重装Win7,Win10只能重装Win10。鉴于这是一篇傻瓜式教程,怎么修改BIOS以及硬盘分区表格式等等这次暂时不教,先学会重装。如果你真的很需要,百度有全面的教程,照做一般没啥问题。
如果你只是想重置系统,请继续往下翻。
如果你想保留个人数据而不是重装一个系统,或者电脑出了问题以下方法不适用,请往下翻参照:【教程五】Win10万能恢复 基本上可以解决操作系统系统带来的各种问题以及绝大部分__蓝屏__。
【教程一】Windows系统重装前言一般来说,有3种装机方式
使用PE盘安装,用制作工具将U盘里装入一个PE系统(精简版Windows),然后重启电脑进入U盘,用PE系统里自带的工具,来完成重装。
相比起其他方式,PE U盘装机的好处是可以随时随地给任何电脑装机,可以通过PE系统里的工具进行分区、引导修复、密码清除等等,同时因为可以访问硬盘,在你系统崩溃的时候,抢救出原系统里的文件。
常用的PE制作工具有:
无广告无捆绑的:微PE,优启通;
有广告有捆绑但可以关闭的:电脑 ...
EduCoder 传输层协议分析
EduCoder 传输层协议分析
关卡1: TCP 包基础
了解 TCP 数据包结构及格式,以及其具体的含义。
关卡2: 三次握手
分析 TCP 的三次握手的具体过程。
关卡3: 拥塞控制
了解拥塞控制,掌握重传机制。
关卡4: UDP 包分析
能够掌握简单的 UDP 包分析。
0x01 TCP 包基础0x0101 相关知识为了完成本关任务,你需要掌握:
理解并掌握 TCP 报文段标记的具体含义;
在 Wireshark 抓包软件中分析 TCP 报文。
TCP 首部格式
源端口( 16 位):通信发送方使用的端口号
目标端口( 16 位):通信接收方使用的端口号
序列号( 32 位):用来确保数据可靠传输的唯一值
确认号( 32 位):接收方在响应时发送的数值
数据偏移( 4 位):标志数据包开始的位置,TCP 头部的长度
标记( 12 位/ 6 位):SYN:(同步)发起连接的数据包:同步 SYN=1 表示这是一个连接请求或连接接受报文。ACK:(确认)确认收到的数据包:只有当 ACK=1 时,确认号字段才有效;当 ACK=0 时,确认号无效。RST:(重置)之前尝试的连接被关闭,(信号差,信号拥挤):当 RST=1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。FIN ...
[数据结构]循环链表
循环链表(Circular LinkList)循环链表有以下两种:
循环单链表: 从一个结点出发只能找到后续的各个结点.
循环双链表: 从一个结点出发可以找到其他任何一个结点.
0x01 循环单链表
单链表和循环单链表的区别:
单链表: 表尾结点的next指针指向NULL
循环单链表: 表尾结点的next指针指向头结点
循环单链表的定义和单链表一样, 如下所示:
123456struct LNode{ //定义单链表结点类型 ElemType data;//每个节点存放一个数据元素 struct LNode *next; //指针指向下一个节点};typedef struct LNode LNode;typedef struct LNode *LinkList;
或者,
1234typedef struct LNode{ //定义单链表结点类型 ElemType data;//每个节点存放一个数据元素 struct LNode *next; //指针指向下一个节点}LNode, *LinkList;
两者等价。
0x0101 循环单链表的初始化123456789101112/*** * @description: 初始化一个循环单链表 * @param {LinkList&} L * @re ...
EduCoder NAT协议分析
EduCoder NAT协议分析关卡1 : 掌握抓取 NAT HOME 端和 NAT ISP 端的具体步骤,并且对已经收集到的 NAT HOME 进行分析。
关卡2 : 对已经收集到的 NAT ISP 进行分析,在路由器和 ISP 之间的链路上捕获的跟踪文件NAT_ISP_side中找到这两个 HTTP 消息和两个 TCP 报文。
0x01 NAT HOME分析0x0101 相关知识为了完成本关任务,你需要掌握:
简单了解实验抓包收集方案.
NAT HOME的简单分析.
0x0102 实验流程(1) 打开 Wireshark,加载实训文件夹中的NAT_home_side文件并筛选出其中的 HTTP 报文;
过滤器中输入http筛选HTTP报文:
(2) 客户端的 IP 地址是多少?填写到文件中;
分析所给流量包中的数据可知其中的私有IP地址为: 192.168.1.100
或者通过Terminal输入指令: ifconfig(Windows为ipconfig)得到.
(3)在 Wireshark 过滤器输入以下过滤式http && ip.addr == 64.233.169.104 ;
(4)选择在 7.109267s 时间的客户端发送到 Google 服务器的 HTTP GET。请问此 HTTP GET 的 IP 数据报上的源 IP 地址和目标 IP ...
[数据结构]双链表
双链表(Double LinkList)在单链表中, 无法逆向检索, 有时候不太方便, 于是有了双链表.
单链表只包含指向后继结点的指针, 双链表则是在单链表的基础上增加了一个指针域prior用于指向前驱结点.
0x01 双链表的定义1234typedef struct DNode { //定义双链表结点类型 int data; //数据域 struct DNode* prior, * next; //前驱指针和后继指针}DNode, * DLinklist;
或者:
123456struct DNode { //定义双链表结点类型 int data; //数据域 struct DNode* prior, * next; //前驱指针和后继指针};typedef struct DNode Dnode;typedef struct DNode * DLinklist;
两者等价.
0x02 双链表的初始化双链表中有前驱指针和后继指针, 初始化一个双链表时前驱指针和后继指针所指向的都是NULL.
双链表头指针的前驱指针和末尾结点的后继指针所指向的永远为NULL.
123456789101112/*** * @description: 初始化双链表 * @param {DLinklist& ...
[数据结构]线性表中的单链表
链表(Linked List)链表是由链式存储的方式实现的顺序表。(不支持随机存取)
0x01 单链表
顺序表(顺序存储):
优点:可随机存取,存储密度高
缺点:要求大片连续空间,改变容量不方便
单链表(链式存储):
优点:不要求大片连续空间,改变容量方便
缺点:不可随机存取,要耗费一定空间存放指针
0x0101单链表的实现123456struct LNode{ //定义单链表结点类型 ElemType data;//每个节点存放一个数据元素 struct LNode *next; //指针指向下一个节点};typedef struct LNode LNode;typedef struct LNode *LinkList;
或者,
1234typedef struct LNode{ //定义单链表结点类型 ElemType data;//每个节点存放一个数据元素 struct LNode *next; //指针指向下一个节点}LNode, *LinkList;
两者等价。
要表示一个单链表时,只需声明一个头指针L,指向单链表的第一个节点:
1LNode *L; //声明一个指向单链表第一个节点的指针
或者,
1LinkList L; //声明一个指向单链表第一个节点的指针(此方法可读性更强)
强调这是一个单链表 – ...
并查集
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091#include<iostream>#include<map>using namespace std;map<string, string> leader;/*** *并查集: *如果要判断两个人是否属于一个朋友圈,只需要判断他们的leader是否为同一个人,这是一个查询的过程. *如果两个人是好友关系,则需要把两个人并入同一个朋友圈,这是一个合并的过程. **///每一行表示朋友关系string input[] = { "周芷若","张无忌", "张无忌","韩小昭", "成昆","陈友谅", "杨逍","纪晓芙",};//测试每行的两人是否为朋友string test[] = { &qu ...
[数据结构]线性表中简单的顺序表
线性表(Linear List)线性表是具有相同数据类型,每个数据元素所占空间一样大的n个数据元素的有限序列(有次序)。
L=($a_1,a_2,…,a_i,a_{i+1},…,a_n$)
其中$a_i$是线性表中的“第i个”元素线性表中的位序
$a_1$是表头元素;$a_n$是表尾元素。
除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继。
0x01 线性表的常用实现函数:InitList(&L): 初始化表。构造一个空的线性表L,分配内存空间。DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间。
ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值。
LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素。GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值。
其他常用操作: Length(L):求表长。返回线性表L的长度,即L中数据元素的个数。PrintList(L):输出操作。按前后顺序输出线性表L的所有元素值。Empty(L):判空操作。若L为空表,则返回true,否则返回 ...
使用Python库分离RSA的n和e
Python分离RSA公钥的n和e参数直接打开公钥文件通过RSA.importKey(key).n和 RSA.importKey(key).e进行处理:
12345678from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEPimport gmpy2import base64import rsapub = open(r"~/key.pub",'r').read()n = RSA.importKey(pub).ne = RSA.importKey(pub).e
基于RSA的非对称加密算法加密SSH远程管理
基于RSA的非对称加密算法加密SSH远程管理0x01 前言:一般的密码方式登录,容易有密码被暴力破解的问题。所以,一般我们会将 SSH 的端口设置为默认的 22 以外的端口,或者禁用 root 账户登录。其实,有一个更好的办法来保证安全,而且让你可以放心地用 root 账户从远程登录——那就是通过密钥方式登录。
密钥形式登录的原理是:利用密钥生成器制作一对密钥——一只公钥和一只私钥。将公钥添加到服务器的某个账户上,然后在客户端利用私钥即可完成认证并登录。这样一来,没有私钥,任何人都无法通过 SSH 暴力破解你的密码来远程登录到系统。此外,如果将公钥复制到其他账户甚至主机,利用私钥也可以登录。
下面来讲解如何在 Linux 服务器上制作密钥对,将公钥添加给账户,设置 SSH,最后通过客户端登录。
0x02 制作密钥对首先在服务器上制作密钥对。首先用密码登录到你打算使用密钥登录的账户,然后执行以下命令:
123456789101112131415161718192021 [root@q1jun ~]# ssh-keygenGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):#这里直接回车,使用默认地址 Enter passphrase (empty ...
WebGoat 网安攻击模拟训练笔记
WebGoat 网安攻击模拟训练笔记1 SQL语句注入1.1 命令注入—Command Injection1.1.1 操作说明右键左边选择框的组建,点击检查,在<option>标签中末尾添加 & ifconfig
然后点击 View 按钮执行,下方显示 ifconfig(Windows下为ipconfig)命令的输出结果
1.1.2 结果截图
1.2 数字型SQL注入—Numeric SQL Injection1.2.1 操作说明右键选择框组建,点击检查,修改中的内容为100 or 1=1
修改完成选择对应的内容,然后点击 Go! 按钮执行
1.2.2 结果截图
1.3 日志欺骗—Log Spoofing1.3.1 操作说明通过日志的换行符(%0d%0a)来欺骗管理员,输入:q1jun%0d%0aLogin Succeeded for username: admin
点击login后:
1.3.2 结果截图
1.4 SQL字符串注入—String SQL Injection1.4.1 操作说明在输入框中输入 Smith ` or 1=1 – 使得查询SQL语句为:
1SELECT * FROM user_data WHERE last_name = 'Smith' or 1=1--'
最后 ...
GoLang 切片
Go 切片: 用法与本质0x01 引言Go的切片类型为处理同类型数据序列提供一个方便而高效的方式。 切片有些类似于其他语言中的数组,但是有一些不同寻常的特性。 本文将深入切片的本质,并讲解它的用法。
0x02 数组(Array)Go的切片是在数组之上的抽象数据类型,因此在了解切片之前必须要先理解数组。
数组类型定义了长度和元素类型。例如, [4]int 类型表示一个四个整数的数组。 数组的长度是固定的,长度是数组类型的一部分( [4]int 和 [5]int 是完全不同的类型)。 数组可以以常规的索引方式访问,表达式 s[n] 访问数组的第 n 个元素。
1234var a [4]inta[0] = 1i := a[0]// i == 1
数组不需要显式的初始化;数组的零值是可以直接使用的,数组元素会自动初始化为其对应类型的零值:
1// a[2] == 0, int 类型的零值
类型 [4]int 对应内存中四个连续的整数:
Go的数组是值语义。一个数组变量表示整个数组,它不是指向第一个元素的指针(不像 C 语言的数组)。 当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组。 (为了避免复制数组,你可以传递一个指向数组的指针,但是数组指针并不是数组。) 可以将数组看作一个特殊的struct,结构的字段名对应数组的索引,同时成员的数目固定。
数组的字面值像这样:
1b ...