题解 # 2850

由于制图麻烦,本题解将以文字叙述。

解题思路

问题分析

这道题主要包含五个过程

init_linked_list
read_structs_into_list
insertion_sort
write_list_into_structs
clear_list

涉及简单链表操作和输入输出问题

数据结构

链表所有单元均以指针形式存放

以结构组定义学生数据

struct student
{
    long id;
    string name;
    string dept;
    string group;
    string type;
    string email;
    long long cell;
};

以双向链表存储数据

struct link_node
{
    student * data;
    link_node * next;
    link_node * prev;
};

并以头尾哨兵维护链表

link_node * init_linked_list()
{
    link_node * head = new link_node;
    link_node * tail = new link_node;

    head->next = tail;
    head->prev = NULL;
    head->data = NULL;

    tail->next = NULL;
    tail->prev = head;
    tail->data = NULL;

    return head;
}

标准输入输出

读取

输入每个学生信息占一行,每个字段以制表符 \t 分割,因此以文件结束 EOF 作为数据末标志,即 while (not cin.eof()),并在输入时不断更新链表信息

node->data = stu;
node->next = tail;
node->prev = ptr;
ptr->next = node;
tail->prev = node;
ptr = node;

即先维护新增节点 node 的链接,再将前后指针指向 node

输出

定义了顺序输出和倒序输出两种方案,以参数 reverse 作为标志

对于顺序输出,从 head 遍历到指针尾 tail 即可

if (head->next->next == NULL)
{
    cout << "EMPTY!" << endl;
}
else
{
    link_node * ptr = head->next;
    while (ptr->next != NULL)
    {
        print_student(ptr->data);
        ptr = ptr->next;
    }
}

对于倒序输出,采用递归的方案

if (head->next == NULL)
{
    return;
}
else
{
    if (head->prev == NULL)
    {
        write_list_into_structs(head->next, reverse = true);
    }
    else
    {
        write_list_into_structs(head->next, reverse = true);
        print_student(head->data);
    }
}

插入排序

算法相对朴素,不断向前比较键值大小,为保持排序稳定注意在相等时结束比较

需要注意的是链表交换数据块的操作

node->prev->next = node->next;
node->next->prev = node->prev;
node->next = pos->next;
node->prev = pos;
pos->next->prev = node;
pos->next = node;

先把当前块 node 的前后两块链接,然后维护 node 使其前后指针指向正确区块,再将前后区块指向 node 即可

释放内存

从头遍历链表并释放内存,最后重新头尾相接

link_node * ptr = head;
link_node * node = ptr;
while (ptr->next != NULL)
{
    node = ptr->next;
    delete ptr;
    ptr = node;
}
head->next = ptr;
ptr->prev = head;

测试过程

完整性测试

首先顺序输出,证明顺序指针完整

由于插入排序依赖倒序指针,因此再次插入排序,证明倒序指针完整

稳定性测试

构建数据进行测试

内存清理测试

在清理完内存后再次输出,若为空则内存清理完毕

数据结构作用

双向链接

在插入排序中需要不断与前一个数据块比较顺序,若为单向指针则必须不断从头遍历,而双向指针可以直接寻找到上一个数据块

头尾哨兵

每次对链表操作都需要头哨兵作为内存地址开始

尾哨兵在测试中发挥了一些作用

简介

在二娘群聊区 发糖骗糖串 已经成为常态,虽已有发糖插件但一个一个 UID 输入十分繁琐。
所以我基于 Python 编写了基于群聊区自动发糖的脚本供各位使用~
首先放出 GitHubGayHub 项目地址:

https://github.com/sulf1ron/u2

喜欢的话欢迎 Watch + Star + Fork + Follow 四连~

脚本特性

对发糖串进行切割,(自动处理)
检测并去除表情符号,(防止混淆)
读取 UID 并检测坏人,(防骗糖 233)
预处理 UID 是否存在,(防止领糖者手滑)
U2娘掉线检测,离线时自动重试(确保发糖进程完整)
……

更新日志

之前的懒得写了(躺)
有兴趣的去看 GitHub 历史吧
2018.02.07 00:08 : 发布 + 教程
2018.02.09 16:33 : 大于5金分割处理 + 优化代码

未来展望

大于 5金 分割处理
论坛链接发糖
……


那么接下来就开始教程部分了!


下载脚本

所需文件

requirements.txt # 依赖列表
api.py           # 基础 API
settings.sample  # 通行证配置样例
sweet.py         # 发糖脚本

配置通行证

浏览器 console 中输入:

document.cookie

填入 settings.sample 中并改名为 settings.ini

配置 Python3

安装

版本号:(理论上 Python3 均可)

> python -V
Python 3.6.3

建议使用相同版本:

https://www.python.org/downloads/release/python-363

依赖

pip install -r requirements.txt

若国内连接性不佳可以换用国内源如:(添加参数)

-i https://pypi.tuna.tsinghua.edu.cn/simple
-i https://mirrors.aliyun.com/pypi/simple

开始使用

运行

python sweet.py

根据详细的提示操作即可

说明

坏人:同一发糖串多次领糖的坏蛋 QAQ,如:

44929 [em28] <-- ...  <--  44929 [em28]

预处理:检测 UID 是否存在

常见错误

等你们反馈了(懒)

报错

若出现报错请先根据提示信息尝试解决
若无法解决或确认为非环境原因bug请发 issue 反馈:

https://github.com/sulf1ron/u2/issues

简介

SSH 验证身份有两种方式:密码和密钥,前者不安全,可能会被爆破,而且不便捷,每次登陆时都需要输入密码。因此,我们可以使用密钥登陆,安全便捷。

本地

首先在本地创建公私钥:

ssh-keygen

按提示操作保存证书,可以给私钥设定密码,也可回车跳过,创建完成后会得到公钥id_rsa.pub和私钥id_rsa

远程

scp ~/.ssh/id_rsa.pub user@server:/home/user/

id_rsa.pub上传至服务器(通过 SCP,SFTP 等)。

cat id_rsa.pub > ~/.ssh/authorized_keys

然后将公钥加入信任列表,

chmod 600 authorized_keys
chmod 700 ~/.ssh

确保文件权现正确。

PasswordAuthentication no
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

编辑配置文件/etc/ssh/sshd_config,加入或修改以上几行。

service ssh restart
service sshd restart

重启SSH服务,并尝试登陆,若无需输入密码直接登陆则说明配置成功。

附加

除了更改为密钥登陆,SSH端口的设置也影响到安全性,使用默认的22端口会极大增加被爆破的可能性。

Port 8789

建议修改/etc/ssh/sshd_config中端口至非22。


概述

吸引用户的是内容,而不是平台。但一个优秀的平台可以让内容增色不少,大幅提升用户的阅读体验。那么,本篇文章就意在让潜在的作者不被博客平台所困扰,从零开始搭建属于自己的博客。
本文需要用户具备基本信息素养及学习查询能力

服务器

首先先租一台虚拟专用服务器VPS,记录IP并连上它(不同操作系统系统所需工具与方法不同,谷歌一下登进去就行,在此不再赘述)。因为笔者喜好,选用 LAMP 这一套主流软件(Ubuntu 18 + Apache2 + MySQL5.7 + PHP7.2),分别代表操作系统、网站服务器软件,数据库以及超文本预处理器。
操作系统在租用 VPS 的时候会提供选择,如果有 Ubuntu 18.04 则选择它,如果没有就选择 Ubuntu 16/14.04 然后执行 do-release-upgrade升级至 18.04。

apt update
apt upgrade

执行基本软件升级操作,根据屏幕提示输入y
一般互联网内容提供商IDC直接允许root登陆,若不然则需在每条命令前加上sudo,可以参照这篇文章为服务器设置密钥登陆增强安全性。

域名

去阿里云之类的域名商买一个心仪的域名,去 DNS 管理器中设置一个@A解析至IP

LAMP

apt install apache2
apt install mysql-server
apt install php7.2 php7.2-mysql php7.2-mbstring php7.2-curl libapache2-mod-php7.2
apt install nano git unzip

利用包管理器(APT)安装软件,十分迅速。

mysql_secure_installation

设置 MySQL 密码,并进行安全加固(建议全部应用)
非 root 身份执行 mysql_secure_installation时请使用sudo

cd /var/www/html

切换到网站默认目录,

nano info.php

用文本编辑器nano创建info.php

<?php
phpinfo();
?>

并输入以上内容,CTRL+O保存,CTRL+X退出。
浏览器中访问IP/info.php,若正常显示相关信息则配置正常。

Typecho

Typecho 是一款轻量级的博客软件,而且插件与外观颇丰。

cd /var/www
wget http://typecho.org/downloads/1.1-17.10.30-release.tar.gz
tar zxvf 1.1-17.10.30-release.tar.gz
rm 1.1-17.10.30-release.tar.gz
mv build typecho

下载 Typecho 并解压。

Vhost

cd /etc/apache2/sites-available
nano typecho.conf

进入 Apache2 网站目录并创建typecho.conf

<VirtualHost *:80>
        ServerName sorx.tech
        ServerAdmin i@sor.moe
        DocumentRoot /var/www/typecho

        <Directory "/var/www/typecho/">
                Options FollowSymLinks
                AllowOverride All
                Order deny,allow
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/typecho.error.log
        CustomLog ${APACHE_LOG_DIR}/typecho.access.log combined
</VirtualHost>

写入以上内容,替换域名与邮箱,并保存退出。

a2enmod rewrite
a2ensite typecho.conf
systemctl restart apache2

开启重写插件并启用网站。

MySQL

mysql -u root -p

输入密码进入MySQL控制台,输入create database typecho;创建新数据库,exit退出。

安装

随后浏览器打开域名,按照提示安装即可。

进阶

地址重写

cd /var/www/typecho
nano .htaccess

创建.htaccess文件,

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]

写入如上内容,然后在https://blog.sorx.tech/admin/options-permalink.php 界面中开启(不用理会错误提示)

SSL

HTTPS 协议可以有效防止被运营商劫持等流氓问题,因此建议为博客配置 SSL。

curl https://get.acme.sh | bash

acme.shLet's Encrypt 的一款第三方工具,可以提供免费 SSL 证书。

cd ~/.acme.sh
./acme.sh --issue -d *.sorx.tech -d sorx.tech --dns dns_azure

使用acme.sh签发证书,DNS API 配置说明见

nano /etc/apache2/sites-available/typecho.conf

然后编辑 Vhost 配置文件,

<VirtualHost *:443>
        ServerName sorx.tech
        ServerAdmin i@sor.moe
        DocumentRoot /var/www/sorx.tech

        <Directory "/var/www/sorx.tech/">
                Options FollowSymLinks
                AllowOverride All
                Order deny,allow
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/sorx.tech.error.log
        CustomLog ${APACHE_LOG_DIR}/sorx.tech.access.log combined

        SSLCertificateFile /home/sor/.acme.sh/*.sorx.tech/fullchain.cer
        SSLCertificateKeyFile /home/sor/.acme.sh/*.sorx.tech/*.sorx.tech.key
        Include /etc/ssl/options-ssl-apache.conf
</VirtualHost>

参照示例更改,并systemctl reload apache2刷新 Apache2

robots.txt

cd /var/www/typcheo
nano robots.txt

robots.txt 告诉搜索引擎哪些可以收录,并告知其站点地图。

User-agent: *
Disallow: /admin/
Disallow: /install/
Allow: /
sitemap: https://blog.sorx.tech/sitemap.xml

写入以上内容,保存退出。

外观与插件

https://github.com/zgq354/typecho-theme-next
https://github.com/journey-ad/MDRuby-Typecho-Plugin
https://github.com/journey-ad/HyperMD-Typecho-Plugin
https://github.com/kokororin/typecho-plugin-Access

本站目前使用的如上,在 repo 页都有详细说明,可以自行选择安装。