diff --git "a/2024/01/09/GitHub desktop\345\237\272\346\234\254\347\224\250\346\263\225/index.html" "b/2024/01/09/GitHub desktop\345\237\272\346\234\254\347\224\250\346\263\225/index.html" index bd0e9aa..1422eec 100644 --- "a/2024/01/09/GitHub desktop\345\237\272\346\234\254\347\224\250\346\263\225/index.html" +++ "b/2024/01/09/GitHub desktop\345\237\272\346\234\254\347\224\250\346\263\225/index.html" @@ -1 +1,14 @@ -GitHub desktop 基本用法 - 马锦的博客

GitHub desktop 基本用法

一,仓库

1.1新建仓库

1,点击File,再点击new repository。

2,通过新建仓库可以实时的在GitHub和GitHub desktop中创建一个空的仓库,你可以对新建的仓库进行各项设置。

包括仓库名字,仓库描述,仓库本地位置,自动创建readme文件,忽略文件的选择,以及开源许可证的选择。这里介绍后两个的详细内容:

git ignore可以选择忽略文件,如果你有些文件并不想上传,那你就可以将其设置。

以下是一个示例 .gitignore 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13

# Ignore node_modules folder 忽略文件夹
node_modules/

# Ignore build artifacts 忽略目录
build/
dist/
*.log

# Ignore configuration files 忽略文件
.env
config.js

这将忽略 node_modules 文件夹、build 和 dist 目录、所有以 .log 结尾的文件以及 .env 和 config.js 文件。

license为许可证设置,设置许可证的目的是为了让别人可以合理合法地使用与修改我们的代码,有多种许可证可以选择,它们具有不同的权限设置。

总结一下,MIT 最自由,简直就是没有任何限制,任何人都可以售卖我的软件,甚至可以用我的名字促销。BSD 和 Apache 协议也很自由,跟 MIT 的区别分别是不允许用作者本人名义促销和保护作者版权。GPL 可以说最霸道,对代码的修改部分也必须是 GPL 的,同时基于 GPL 代码而开发的代码也必须按照 GPL 发布,而 MPL ,也就是 Mozilla Public License 就温和一些,如果后续开发的代码中添加了新文件,同时新文件中也没有用到原来的代码,那么新文件可以不必继续沿用 MPL 。【如何为自己的 Github 项目选择开源许可证? - 知乎 (zhihu.com)

3,当你完成了前两步,你还需要点击Publish repository来上传仓库,并设置仓库是否公开(这很重要!)

1.2添加本地仓库

1,点击File,再点击Ddd local repository。

2,输入本地文件地址,但如果你的文件未初始化为git仓库,则需要点击create a repository来新建一个仓库(作用是将选定的文件初始化为git仓库)

3,点击后则与上面一样,进行各种参数填充。

1.3克隆仓库

1,点击File,再点击Clone repository。

2,选择需要克隆的仓库,如果你是要克隆别人的仓库,可以选择URL

1.4编辑仓库

  • 点击open in ········,如果这个编辑器不是你喜欢的,你可以点击绿色的Options进行编辑器的选择。

1.5删除仓库

  • 删除仓库并不会删除GitHub上的仓库,更多的作用是删除本地与GitHub的连接!

如果你想切断GitHub与本地库的连接,你可以执行以下操作:

  1. 删除本地库中的.git文件夹(这是一个隐藏文件夹,你需要启用显示隐藏文件夹选项)

  2. 如果你想从GitHub上删除该库,你可以在GitHub上进入该库,点击“Settings”,然后在“Danger Zone”中点击“Delete this repository”。

这里推荐使用GitHub desktop进行删除操作:

右击需要删除的仓库

在被删除仓库页面,点击Repository,再点击Remove

你会看到如下页面,勾选下方选项框的话,会将你的仓库从计算机硬盘中移除;如果不勾选,只会在GitHub desktop(GitHub)上移除。

二,版本控制

2.1更新版本

1,GitHub desktop会自动识别仓库里代码的变动,并且你可选择应用哪些改变。如果你改变了仓库链接的本地仓库文件,你可以在GitHub desktop的主页面上看到如下场景:

我在仓库中新建了‘版本更新.py’文件,并在其中写入了print(’dddd’)代码

2,可以看到左侧栏中出现了changes,你需要在左下角的summary中填入摘记(必填),还可以填入相关描述,填入后,你还需要点击Push origin上传:

3,这时你就可以在GitHub上看到你的仓库发生了变化:

2.2项目回滚

1,你可以在History里看到每一次的版本变化:

2,具体操作:

  • 点击History
  • 选择要回滚的版本
  • 右键选择Revert Changes in Commit
  • 确认回滚信息并提交

可以看到版本回到了最开始的样子。

三,分支管理

3.1新建分支

  • 点击Current brance
  • 点击New brance
  • 然后为你的分支命名即可
  • 在GitHub中查看分支

创建分支

3.2切换分支

点击即可

在GitHub desktop选择分支

在GitHub查看与选择分支

3.3合并分支

  1. 首先,在 GitHub Desktop 中打开你要合并的仓库。

  2. 点击左侧导航栏中的“分支”选项卡,找到你要合并的分支。

  3. 选择要合并的分支,右键点击该分支并选择“Merge into current branch”(合并到当前分支)选项。

  4. 确认合并操作,如果有冲突需要手动解决冲突。

  5. 点击“Commit merge”(提交合并)按钮。

  6. 最后点击“Push origin”(推送到远程仓库)按钮,将合并后的代码推送到远程仓库。

3.4删除分支

  • 右键删除即可

3.5比较分支

  • 在 GitHub Desktop 中打开你要合并的仓库。
  • 点击Compare to brance

  • 在左侧搜索需要对比的即可

3.6查看提交历史

  • 在想要查看的分支下点击Hitory

四,多人协作

  1. 创建GitHub仓库:首先,一个人(通常是项目的负责人)在GitHub上创建一个仓库,并将其与本地项目相关联。
  2. 邀请协作者:负责人可以通过在GitHub仓库的设置中添加协作者来邀请其他人加入项目。在协作者的GitHub帐户上,他们将收到邀请加入项目的通知。

在仓库设置里,点击Collabarators即可

  1. 克隆仓库:协作者使用GitHub Desktop克隆项目的仓库到本地。他们可以选择克隆到自己的计算机上的任意位置。
  2. 进行更改:每个协作者在本地进行代码更改或其他操作。他们可以使用GitHub Desktop的界面进行提交更改。
  3. 提交更改:协作者完成更改后,使用GitHub Desktop提交他们的更改到GitHub仓库。他们可以添加有关更改的说明和描述。
  4. 解决冲突:如果两个或多个协作者在相同的文件的相同行进行了更改,可能会出现冲突。在这种情况下,GitHub Desktop会提醒协作者,让他们解决冲突。协作者可以使用GitHub Desktop提供的冲突解决工具来处理冲突。
  5. 更新本地仓库:协作者可以通过点击GitHub Desktop中的”Pull”按钮来获取最新的更改。这将从GitHub仓库中拉取其他协作者提交的更改并合并到本地仓库。

  1. 推送更改:协作者在本地完成更改后,可以使用GitHub Desktop的”Push”按钮将更改推送到GitHub仓库。这将把他们的更改上传到仓库并使其他协作者可见。

通过这些步骤,多人可以使用GitHub Desktop进行协作开发,并实时共享和同步他们的更改。在整个过程中,GitHub Desktop提供了一个简单直观的界面,帮助协作者进行版本控制和协作。


GitHub desktop 基本用法
https://jimes.cn/2024/01/09/GitHub desktop基本用法/
作者
Jimes
发布于
2024年1月9日
许可协议
\ No newline at end of file +GitHub desktop 基本用法 - 马锦的博客

GitHub desktop 基本用法

一,仓库

1.1新建仓库

1,点击File,再点击new repository。

2,通过新建仓库可以实时的在GitHub和GitHub desktop中创建一个空的仓库,你可以对新建的仓库进行各项设置。

包括仓库名字,仓库描述,仓库本地位置,自动创建readme文件,忽略文件的选择,以及开源许可证的选择。这里介绍后两个的详细内容:

git ignore可以选择忽略文件,如果你有些文件并不想上传,那你就可以将其设置。

以下是一个示例 .gitignore 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13

# Ignore node_modules folder 忽略文件夹
node_modules/

# Ignore build artifacts 忽略目录
build/
dist/
*.log

# Ignore configuration files 忽略文件
.env
config.js

这将忽略 node_modules 文件夹、build 和 dist 目录、所有以 .log 结尾的文件以及 .env 和 config.js 文件。

license为许可证设置,设置许可证的目的是为了让别人可以合理合法地使用与修改我们的代码,有多种许可证可以选择,它们具有不同的权限设置。

总结一下,MIT 最自由,简直就是没有任何限制,任何人都可以售卖我的软件,甚至可以用我的名字促销。BSD 和 Apache 协议也很自由,跟 MIT 的区别分别是不允许用作者本人名义促销和保护作者版权。GPL 可以说最霸道,对代码的修改部分也必须是 GPL 的,同时基于 GPL 代码而开发的代码也必须按照 GPL 发布,而 MPL ,也就是 Mozilla Public License 就温和一些,如果后续开发的代码中添加了新文件,同时新文件中也没有用到原来的代码,那么新文件可以不必继续沿用 MPL 。【如何为自己的 Github 项目选择开源许可证? - 知乎 (zhihu.com)

3,当你完成了前两步,你还需要点击Publish repository来上传仓库,并设置仓库是否公开(这很重要!)

1.2添加本地仓库

1,点击File,再点击Ddd local repository。

2,输入本地文件地址,但如果你的文件未初始化为git仓库,则需要点击create a repository来新建一个仓库(作用是将选定的文件初始化为git仓库)

3,点击后则与上面一样,进行各种参数填充。

1.3克隆仓库

1,点击File,再点击Clone repository。

2,选择需要克隆的仓库,如果你是要克隆别人的仓库,可以选择URL

1.4编辑仓库

  • 点击open in ········,如果这个编辑器不是你喜欢的,你可以点击绿色的Options进行编辑器的选择。

1.5删除仓库

  • 删除仓库并不会删除GitHub上的仓库,更多的作用是删除本地与GitHub的连接!

如果你想切断GitHub与本地库的连接,你可以执行以下操作:

  1. 删除本地库中的.git文件夹(这是一个隐藏文件夹,你需要启用显示隐藏文件夹选项)

  2. 如果你想从GitHub上删除该库,你可以在GitHub上进入该库,点击“Settings”,然后在“Danger Zone”中点击“Delete this repository”。

这里推荐使用GitHub desktop进行删除操作:

右击需要删除的仓库

在被删除仓库页面,点击Repository,再点击Remove

你会看到如下页面,勾选下方选项框的话,会将你的仓库从计算机硬盘中移除;如果不勾选,只会在GitHub desktop(GitHub)上移除。

二,版本控制

2.1更新版本

1,GitHub desktop会自动识别仓库里代码的变动,并且你可选择应用哪些改变。如果你改变了仓库链接的本地仓库文件,你可以在GitHub desktop的主页面上看到如下场景:

我在仓库中新建了‘版本更新.py’文件,并在其中写入了print(’dddd’)代码

2,可以看到左侧栏中出现了changes,你需要在左下角的summary中填入摘记(必填),还可以填入相关描述,填入后,你还需要点击Push origin上传:

3,这时你就可以在GitHub上看到你的仓库发生了变化:

2.2项目回滚

1,你可以在History里看到每一次的版本变化:

2,具体操作:

  • 点击History
  • 选择要回滚的版本
  • 右键选择Revert Changes in Commit
  • 确认回滚信息并提交

可以看到版本回到了最开始的样子。

三,分支管理

3.1新建分支

  • 点击Current brance
  • 点击New brance
  • 然后为你的分支命名即可
  • 在GitHub中查看分支

创建分支

3.2切换分支

点击即可

在GitHub desktop选择分支

在GitHub查看与选择分支

3.3合并分支

  1. 首先,在 GitHub Desktop 中打开你要合并的仓库。

  2. 点击左侧导航栏中的“分支”选项卡,找到你要合并的分支。

  3. 选择要合并的分支,右键点击该分支并选择“Merge into current branch”(合并到当前分支)选项。

  4. 确认合并操作,如果有冲突需要手动解决冲突。

  5. 点击“Commit merge”(提交合并)按钮。

  6. 最后点击“Push origin”(推送到远程仓库)按钮,将合并后的代码推送到远程仓库。

3.4删除分支

  • 右键删除即可

3.5比较分支

  • 在 GitHub Desktop 中打开你要合并的仓库。
  • 点击Compare to brance

  • 在左侧搜索需要对比的即可

3.6查看提交历史

  • 在想要查看的分支下点击Hitory

四,多人协作

  1. 创建GitHub仓库:首先,一个人(通常是项目的负责人)在GitHub上创建一个仓库,并将其与本地项目相关联。
  2. 邀请协作者:负责人可以通过在GitHub仓库的设置中添加协作者来邀请其他人加入项目。在协作者的GitHub帐户上,他们将收到邀请加入项目的通知。

在仓库设置里,点击Collabarators即可

  1. 克隆仓库:协作者使用GitHub Desktop克隆项目的仓库到本地。他们可以选择克隆到自己的计算机上的任意位置。
  2. 进行更改:每个协作者在本地进行代码更改或其他操作。他们可以使用GitHub Desktop的界面进行提交更改。
  3. 提交更改:协作者完成更改后,使用GitHub Desktop提交他们的更改到GitHub仓库。他们可以添加有关更改的说明和描述。
  4. 解决冲突:如果两个或多个协作者在相同的文件的相同行进行了更改,可能会出现冲突。在这种情况下,GitHub Desktop会提醒协作者,让他们解决冲突。协作者可以使用GitHub Desktop提供的冲突解决工具来处理冲突。
  5. 更新本地仓库:协作者可以通过点击GitHub Desktop中的”Pull”按钮来获取最新的更改。这将从GitHub仓库中拉取其他协作者提交的更改并合并到本地仓库。

  1. 推送更改:协作者在本地完成更改后,可以使用GitHub Desktop的”Push”按钮将更改推送到GitHub仓库。这将把他们的更改上传到仓库并使其他协作者可见。

通过这些步骤,多人可以使用GitHub Desktop进行协作开发,并实时共享和同步他们的更改。在整个过程中,GitHub Desktop提供了一个简单直观的界面,帮助协作者进行版本控制和协作。


GitHub desktop 基本用法
https://jimes.cn/2024/01/09/GitHub desktop基本用法/
作者
Jimes
发布于
2024年1月9日
许可协议
+ + \ No newline at end of file diff --git "a/2024/01/10/\344\272\272\345\267\245\346\231\272\350\203\275\345\255\246\344\271\240\345\257\274\350\210\252/index.html" "b/2024/01/10/\344\272\272\345\267\245\346\231\272\350\203\275\345\255\246\344\271\240\345\257\274\350\210\252/index.html" index 2c1ff8f..3b6450c 100644 --- "a/2024/01/10/\344\272\272\345\267\245\346\231\272\350\203\275\345\255\246\344\271\240\345\257\274\350\210\252/index.html" +++ "b/2024/01/10/\344\272\272\345\267\245\346\231\272\350\203\275\345\255\246\344\271\240\345\257\274\350\210\252/index.html" @@ -1 +1,14 @@ -人工智能学习导航 - 马锦的博客

人工智能学习导航

1,机器学习算法python实现

GitHub项目,讲解了机器学习算法的数学原理与python实现,做笔记必备。

2,Hello算法

数据结构类的算法的多方式实现,有c,python,c++等等,同时配备了可视化界面,形象讲解算法的原理与区别。

3,可视化数据结构与算法

一个单纯模拟数据结构算法的网站。

4,菜鸟教程

学计算机必备,各种语言与第三方库的讲解以及框架,数不胜数!

5,神经网络与深度学习

邱锡鹏教授出版,详细功能见网址上级GitHub仓库,具有以下特点:

系统性:系统地整理了神经网络和深度学习的知识体系。鉴于深度学习涉及的知识点较多,本书从机器学习的基本概念、神经网络模型以及概率图模型三个层面来串联深度学习所涉及的知识点,使读者对深度学习技术的理解更具系统性、条理性和全面性。
可读性:本书在编排上由浅入深,在语言表达上力求通俗易懂,并通过增加图例、示例以及必要的数学推导来理解抽象的概念。同时,附录简要介绍了本书所涉及的必要数学知识,便于读者查用。
实践性:本书在网站上配套了针对每章知识点的编程练习,使得读者在学习过程中可以将理论和实践密切结合,加深对知识点的理解,并具备分析问题和解决问题的能力。

6,小林coding

图解计算机网络、操作系统、计算机组成、数据库,让天下没有难懂的八股文!


人工智能学习导航
https://jimes.cn/2024/01/10/人工智能学习导航/
作者
Jimes
发布于
2024年1月10日
许可协议
\ No newline at end of file +人工智能学习导航 - 马锦的博客

人工智能学习导航

1,机器学习算法python实现

GitHub项目,讲解了机器学习算法的数学原理与python实现,做笔记必备。

2,Hello算法

数据结构类的算法的多方式实现,有c,python,c++等等,同时配备了可视化界面,形象讲解算法的原理与区别。

3,可视化数据结构与算法

一个单纯模拟数据结构算法的网站。

4,菜鸟教程

学计算机必备,各种语言与第三方库的讲解以及框架,数不胜数!

5,神经网络与深度学习

邱锡鹏教授出版,详细功能见网址上级GitHub仓库,具有以下特点:

系统性:系统地整理了神经网络和深度学习的知识体系。鉴于深度学习涉及的知识点较多,本书从机器学习的基本概念、神经网络模型以及概率图模型三个层面来串联深度学习所涉及的知识点,使读者对深度学习技术的理解更具系统性、条理性和全面性。
可读性:本书在编排上由浅入深,在语言表达上力求通俗易懂,并通过增加图例、示例以及必要的数学推导来理解抽象的概念。同时,附录简要介绍了本书所涉及的必要数学知识,便于读者查用。
实践性:本书在网站上配套了针对每章知识点的编程练习,使得读者在学习过程中可以将理论和实践密切结合,加深对知识点的理解,并具备分析问题和解决问题的能力。

6,小林coding

图解计算机网络、操作系统、计算机组成、数据库,让天下没有难懂的八股文!


人工智能学习导航
https://jimes.cn/2024/01/10/人工智能学习导航/
作者
Jimes
发布于
2024年1月10日
许可协议
+ + \ No newline at end of file diff --git "a/2024/01/12/python\347\250\213\345\272\217\345\270\246\345\233\276\347\211\207\347\255\211\350\265\204\346\272\220\346\211\223\345\214\205/index.html" "b/2024/01/12/python\347\250\213\345\272\217\345\270\246\345\233\276\347\211\207\347\255\211\350\265\204\346\272\220\346\211\223\345\214\205/index.html" index d1c848f..56993fa 100644 --- "a/2024/01/12/python\347\250\213\345\272\217\345\270\246\345\233\276\347\211\207\347\255\211\350\265\204\346\272\220\346\211\223\345\214\205/index.html" +++ "b/2024/01/12/python\347\250\213\345\272\217\345\270\246\345\233\276\347\211\207\347\255\211\350\265\204\346\272\220\346\211\223\345\214\205/index.html" @@ -1 +1,14 @@ -python程序带图片等资源打包 - 马锦的博客

python程序带图片等资源打包

1
2
3
#在打包时,都需要将终端运行地址切换到要打包文件的父目录下
#在终端中运行以下代码
cd 父目录地址

1,常规打包

1
2
3
4
5
6
7
Pyinstaller -F py_word.py     #打包成单独exe,在文件夹dist中的单独文件

Pyinstaller -F -w py_word.py  #不带控制台的打包,不建议,会导致静默运行,只能从运行管理器中找到并停止

Pyinstaller -F -w -i chengzi.ico py_word.py  #打包指定exe图标打包

pyinstaller -F --uac-admin word.py #打包的程序以管理员身份运行

如果打包过大,可以使用anaconda创建虚拟环境只下载需要的第三方库。

2,带资源打包

2.1 首先解决的问题:打包后代码里资源的地址会因在不同环境下运行而不同。

首先需要将图片放到代码同级文件夹内,同时更新代码内的图片地址,这样做是为了后期能够批量打包图片等资源。

这里通过文件运行的绝对路径结合图片的相对路径来生成图片的绝对路径。将以下函数代码复制到打包代码中:

1
2
3
4
def get_resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)

定义了函数后,将代码里的图片地址统一换为:

1
get_resource_path('原代码里的图片地址')

2.2 开始进行打包

  1. -add-data后面可以加=,也可以直接空格,效果一样。
  2. -add-data后面的参数值里,有两部分,用 : 或者 ;隔开,前面是指打包前文件所在的位置,后面是指打包后你希望文件所在的位置。比如样例里的:-add-data="image1.png:img" 的意思是把当前目录里一个叫 “image1.png” 的文件打包进去,但是放在打包后的 “img” 目录下,也就是变成 img/image1.png,文件名不变。
  3. -add-data可以用好多次,也就是可以一个文件一个文件地加。
  4. 整个文件夹一起加:-add-data 'images:images' 也就是把当前目录下 images 文件夹里的文件都打包进去,打包后的目录也是 images 一样的文件夹下。

最终在终端运行的代码:

1
pyinstaller --add-data 'images:images' -F --uac-admin py_name.py

python程序带图片等资源打包
https://jimes.cn/2024/01/12/python程序带图片等资源打包/
作者
Jimes
发布于
2024年1月12日
许可协议
\ No newline at end of file +python程序带图片等资源打包 - 马锦的博客

python程序带图片等资源打包

1
2
3
#在打包时,都需要将终端运行地址切换到要打包文件的父目录下
#在终端中运行以下代码
cd 父目录地址

1,常规打包

1
2
3
4
5
6
7
Pyinstaller -F py_word.py     #打包成单独exe,在文件夹dist中的单独文件

Pyinstaller -F -w py_word.py  #不带控制台的打包,不建议,会导致静默运行,只能从运行管理器中找到并停止

Pyinstaller -F -w -i chengzi.ico py_word.py  #打包指定exe图标打包

pyinstaller -F --uac-admin word.py #打包的程序以管理员身份运行

如果打包过大,可以使用anaconda创建虚拟环境只下载需要的第三方库。

2,带资源打包

2.1 首先解决的问题:打包后代码里资源的地址会因在不同环境下运行而不同。

首先需要将图片放到代码同级文件夹内,同时更新代码内的图片地址,这样做是为了后期能够批量打包图片等资源。

这里通过文件运行的绝对路径结合图片的相对路径来生成图片的绝对路径。将以下函数代码复制到打包代码中:

1
2
3
4
def get_resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)

定义了函数后,将代码里的图片地址统一换为:

1
get_resource_path('原代码里的图片地址')

2.2 开始进行打包

  1. -add-data后面可以加=,也可以直接空格,效果一样。
  2. -add-data后面的参数值里,有两部分,用 : 或者 ;隔开,前面是指打包前文件所在的位置,后面是指打包后你希望文件所在的位置。比如样例里的:-add-data="image1.png:img" 的意思是把当前目录里一个叫 “image1.png” 的文件打包进去,但是放在打包后的 “img” 目录下,也就是变成 img/image1.png,文件名不变。
  3. -add-data可以用好多次,也就是可以一个文件一个文件地加。
  4. 整个文件夹一起加:-add-data 'images:images' 也就是把当前目录下 images 文件夹里的文件都打包进去,打包后的目录也是 images 一样的文件夹下。

最终在终端运行的代码:

1
pyinstaller --add-data 'images:images' -F --uac-admin py_name.py

python程序带图片等资源打包
https://jimes.cn/2024/01/12/python程序带图片等资源打包/
作者
Jimes
发布于
2024年1月12日
许可协议
+ + \ No newline at end of file diff --git a/2024/02/02/structure of data of list/index.html b/2024/02/02/structure of data of list/index.html index b0eb4b8..aa6c943 100644 --- a/2024/02/02/structure of data of list/index.html +++ b/2024/02/02/structure of data of list/index.html @@ -1 +1,14 @@ -数据结构之线性表代码 - 马锦的博客

数据结构之线性表代码

一,顺序表

1.1 顺序表的实现

静态实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define MaxSize 10 // 定义最大长度 

typedef struct {
int data[MaxSize]; // 使用静态的数组存放数据元素
int length; // 顺序表的当前长度
}SqList;

// 初始化顺序表
void InitList(SqList &L) {
L.length = 0; // 顺序表初始长度为0
}

int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表
return 0;
}

动态实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#define MaxSize 10 // 定义最大长度 
#define InitSize 10 // 顺序表的初始长度

typedef struct {
int *data; // 声明动态分配数组的指针
int MaxSize; // 顺序表的最大容量
int length; // 顺序表的当前长度
}SeqList;

// 初始化顺序表
void InitList(SeqList &L) {
// 用malloc函数申请一片连续的存储空间
L.data = (int *)malloc(InitSize * sizeof(int));
L.length = 0;
L.MaxSize = InitSize;
}

// 增加动态数组的长度 ,非重点
void IncreaseSize(SeqList &L, int len) {
int *p = L.data;
L.data = (int *)malloc((L.MaxSize+len) * sizeof(int));
for (int i = 0; i < L.length; i++)
L.data[i] = p[i]; // 将数据复制到新区域
L.MaxSize = L.MaxSize + len; // 顺序表最大长度增加len
free(p); // 释放原来的内存空间
}

int main() {
SeqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表
...
IncreaseSize(L, 5);
return 0;
}

malloc() 函数的作用:会申请一片存储空间,并返回存储空间第一个位置的地址,也就是该位置的指针。

1.2 顺序表的基本操作

插入:

1
2
3
4
5
6
7
8
9
10
11
12
// 在顺序表i位置插入e
bool ListInsert(SqList &L, int i, int e) {
if (i < 1 || i > L.length+1) // 判断i的范围是否有效
return false;
if (L.length >= MaxSize) // 判断存储空间是否已满
return false;
for (int j = L.length; j >= i; j--) // 将第i个元素之后的元素后移
L.data[j] = L.data[j-1];
L.data[i-1] = e; // 在位置i处放入e
L.length++; // 长度+1
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

删除:

1
2
3
4
5
6
7
8
9
10
// 删除顺序表i位置的数据并存入e
bool ListDelete(SqList &L, int i, int &e) {
if (i < 1 || i > L.length) // 判断i的范围是否有效
return false;
e = L.data[i-1]; // 将被删除的元素赋值给e
for (int j = i; j < L.length; j++) //将第i个位置后的元素前移
L.data[j-1] = L.data[j];
L.length--;
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

按位查找:

1
2
3
4
5
6
// 静态分配的按位查找
#define MaxSize 10

ElemType GetElem(SqList L, int i) {
return L.data[i-1];
}
1
2
3
4
5
6
// 动态分配的按位查找
#define InitSize 10

ElemType GetElem(SeqList L, int i) {
return L.data[i-1];
}

时间复杂度: O ( 1 )

按值查找:

1
2
3
4
5
6
7
// 查找第一个元素值为e的元素,并返回其位序 
int LocateElem(SqList L, ElemType e) {
for (int i = 0; i < L.length; i++)
if (L.data[i] == e)
return i+1; // 数组下标为i的元素值等于e,返回其位序i+1
return 0; // 没有查找到
}

在《数据结构》考研初试中,手写代码可以直接用“==”,无论 ElemType 是基本数据类型还是结构类型

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

二,单链表

2.1 单链表的实现

不带头结点的单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

//初始化一个空的单链表
bool InitList(LinkList &L){
L = NULL;//空表,暂时还没有任何结点
return true;
}

void test(){
LinkList L;//声明一个指向单链表的头指针
//初始化一个空表
InitList(L);
...
}

//判断单链表是否为空
bool Empty(LinkList L){
return (L==NULL)
}

带头结点的单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 初始化一个单链表(带头结点)
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));//分配一个头结点
if (L == NULL)//内存不足,分配失败
return false;
L->next = NULL;//头结点之后暂时还没有结点
return true;
}

void test(){
LinkList L;//声明一个指向单链表的头指针
//初始化一个空表
InitList(L);
...
}

//判断单链表是否为空
bool Empty(LinkList L){
if (L->next == NULL)
return true;
else
return false;
}

2.2 单链表的建立

尾插法建立单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 使用尾插法建立单链表L
LinkList List_TailInsert(LinkList &L){
int x;//设ElemType为整型int
L = (LinkList)malloc(sizeof(LNode));//建立头结点(初始化空表)
LNode *s, *r = L;//r为表尾指针
scanf("%d", &x);//输入要插入的结点的值
while(x!=9999){//输入9999表示结束
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;//r指针指向新的表尾结点
scanf("%d", &x);
}
r->next = NULL;//尾结点指针置空
return L;
}

时间复杂度:O ( n )

头插法建立单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode));//建立头结点
L->next = NULL;//初始为空链表,这步很关键
scanf("%d", &x);//输入要插入的结点的值
while(x!=9999){//输入9999表结束
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
//将新结点插入表中,L为头指针
scanf("%d", &x);
}
return L;
}

头插法实现链表的逆置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 将链表L中的数据逆置并返回
LNode *Inverse(LNode *L){
LNode *p, *q;
p = L->next;//p指针指向第一个结点
L->next = NULL;//头结点置空
// 依次判断p结点中的数据并采用头插法插到L链表中
while (p != NULL){
q = p;
p = p->next;
q->next = L->next;
L->next = q;
}
return L;
}

2.3 单链表的基本操作

按位序插入(带头结点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return False;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p = L; //循环找到第i-1个结点
while(p!=NULL && j<i-1){ //如果i>lengh,p最后会等于NULL
p = p->next;
j++;
}
//p值为NULL说明i值不合法
if (p==NULL)
return false;
//在第i-1个结点后插入新结点
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
//将结点s连到p后
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

按位序插入(不带头结点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L, int i, ElemType e){
//判断i的合法性
if(i<1)
return false;
//需要判断插入的位置是否是第1个
if(i==1){
LNode *s = (LNode *)malloc(size of(LNode));
s->data =e;
s->next =L;
L=s;//头指针指向新结点
return true;
}
//i>1的情况与带头结点一样,唯一区别是j的初始值为1
LNode *p;//指针p指向当前扫描到的结点
int j=1;//当前p指向的是第几个结点
p = L;
//循环找到第i-1个结点
while(p!=NULL && j<i-1){//如果i>lengh,p最后会等于NULL
p = p->next;
j++;
}
//p值为NULL说明i值不合法
if (p==NULL)
return false;
//在第i-1个结点后插入新结点
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

除非特别声明,否则之后的代码都默认为带头结点

指定结点的后插操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 在结点p后插入元素e
bool InsertNextNode(LNode *p, ElemType e){
if(p==NULL){
return false;
}
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}

// 按位序插入的函数中可以直接调用后插操作
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return False;
LNode *p;
//指针p指向当前扫描到的结点
int j=0;
//当前p指向的是第几个结点
p = L;
//循环找到第i-1个结点
while(p!=NULL && j<i-1){
//如果i>lengh, p最后会等于NULL
p = p->next;
j++;
}
return InsertNextNode(p, e)
}

时间复杂度:O ( 1 )

指定结点的前插操作:

如果传入头指针,就可以循环整个链表找到指定结点p的前驱结点q,再对q进行后插操作;
如果不传入头指针,可以在指定结点p后插入一个结点s,并交换两个结点所保存的数据,从而变相实现指定结点的前插操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 在结点p前插入元素e
bool InsertPriorNode(LNode *p, ElemType e){
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
// 内存不足分配失败
if(s==NULL)
return false;
// 将s插入结点p之后
s->next = p->next;
p->next = s;
// 交换两个结点中的数据
s->data = p->data;
p->data = e;
return true;
}

时间复杂度:O ( 1 )

按位序删除:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct LNode{
ElemType data;
struct LNode *next;}LNode, *LinkList;

// 删除第i个结点并将其所保存的数据存入e
bool ListDelete(LinkList &L, int i, ElemType &e){
if(i<1)
return false;
LNode *p;//指针p指向当前扫描到的结点
int j=0;//当前p指向的是第几个结点
p = L;
//循环找到第i-1个结点
while(p!=NULL && j<i-1){
//如果i>lengh,p和p的后继结点会等于NULL
p = p->next;
j++;
}
if(p==NULL)
return false;
if(p->next == NULL)
return false;
//令q暂时保存被删除的结点
LNode *q = p->next;
e = q->data;
p->next = q->next;
free(q)
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

删除指定结点:

如果传入头指针,就可以循环整个链表找到指定结点p的前驱结点q,再对p进行删除操作;
如果不传入头指针,可以把指定结点p的后继结点q删除,并使结点p保存结点q存储的数据,从而变相实现删除指定结点的操作。但是如果指定结点p没有后继结点,这么做会报错

1
2
3
4
5
6
7
8
9
10
// 删除指定结点p
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q = p->next;// 令q指向p的后继结点// 如果p是最后一个结点,则q指向NULL,继续执行就会报错
p->data = q->data;
p->next = q->next;
free(q);
return true;
}

时间复杂度:O ( 1 )

按位查找:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 查找指定位序i的结点并返回
LNode * GetElem(LinkList L, int i){
if(i<0)
return NULL;
LNode *p;
int j=0;
p = L;
while(p!=NULL && j<i){
p = p->next;
j++;
}
return p;
}

// 封装后的插入操作,在第i个位置插入元素e,可以调用查询操作和后插操作
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return False;
// 找到第i-1个元素
LNode *p = GetElem(L, i-1);
// 在p结点后插入元素e
return InsertNextNode(p, e)
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

按值查找:

1
2
3
4
5
6
7
8
9
// 查找数据域为e的结点指针,否则返回NULL
LNode * LocateElem(LinkList L, ElemType e){
LNode *P = L->next;
// 从第一个结点开始查找数据域为e的结点
while(p!=NULL && p->data != e){
p = p->next;
}
return p;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

计算单链表长度:

1
2
3
4
5
6
7
8
9
10
// 计算单链表的长度
int Length(LinkList L){
int len=0;//统计表长
LNode *p = L;
while(p->next != NULL){
p = p->next;
len++;
}
return len;
}

时间复杂度:O ( n )

三,双链表

双链表的初始化 (带头结点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct DNode{            //定义双链表结点类型
ElemType data; //数据域
struct DNode *prior, *next; //前驱和后继指针
}DNode, *DLinklist;

// 初始化双链表
bool InitDLinkList(Dlinklist &L){
L = (DNode *)malloc(sizeof(DNode));
if(L==NULL)
return false;
L->prior = NULL;//头结点的prior指针永远指向NULL
L->next = NULL;//头结点之后暂时还没有结点,置空
return true;
}

void testDLinkList(){
DLinklist L;
InitDLinkList(L);
...
}

// 判断双链表是否为空
bool Empty(DLinklist L){
if(L->next == NULL)
return true;
else
return false;
}

双链表的后插操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct DNode{
ElemType data;
struct DNode *prior, *next;
}DNode, *DLinklist;

// 将结点s插入到结点p之后
bool InsertNextDNode(DNode *p, DNode *s){
if(p==NULL || s==NULL)
return false;
s->next = p->next;
// 判断结点p之后是否有后继结点
if (p->next != NULL)
p->next->prior = s;
s->prior = p;
p->next = s;
return true;
}

双链表的前插操作、按位序插入操作都可以转换成后插操作

双链表的删除操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 删除p结点的后继结点
bool DeletNextDNode(DNode *p){
if(p==NULL)
return false;
// 找到p的后继结点q
DNode *q =p->next;
if(q==NULL)
return false;
p->next = q->next;
if(q->next != NULL)
q->next->prior=p;
free(q);
return true;
}

// 销毁一个双链表
bool DestoryList(DLinklist &L){
// 循环释放各个数据结点
while(L->next != NULL){
DeletNextDNode(L);
free(L);
// 头指针置空
L=NULL;
}
}

双链表的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 向后遍历
while(p!=NULL){
// 对结点p做相应处理
p = p->next;
}

// 向前遍历
while(p!=NULL){
// 对结点p做相应处理
p = p->prior;
}

// 跳过头结点的遍历
while(p->prior!=NULL){
//对结点p做相应处理
p = p->prior;
}

双链表不可随机存取,按位查找、按值查找操作都只能用遍历的方式实现。

四,循环链表

循环单链表的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typedef struct LNode{           
ElemType data;
struct LNode *next;
}DNode, *Linklist;

// 初始化循环单链表
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));
if(L==NULL)
return false;
// 最后一个结点的next指针指向头结点
L->next = L;
return true;
}

// 判断循环单链表是否为空
bool Empty(LinkList L){
if(L->next == L)
return true;
else
return false;
}

// 判断结点p是否为循环单链表的表尾结点
bool isTail(LinkList L, LNode *p){
if(p->next == L)
return true;
else
return false;
}

循环双链表的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typedef struct DNode{            
ElemType data;
struct DNode *prior, *next;
}DNode, *DLinklist;

// 初始循环双链表
bool InitDLinkList(DLinklist &L){
L = (DNode *) malloc(sizeof(DNode));
if(L==NULL)
return false;
// 头结点的prior指针指向最后一个结点,最后一个结点的next指针指向头结点
L->prior = L;
L->next = L;
}

// 判断循环双链表是否为空
bool Empty(DLinklist L){
if(L->next == L)
return true;
else
return false;
}

// 判断结点p是否为循环双链表的表尾结点
bool isTail(DLinklist L, DNode *p){
if(p->next == L)
return true;
else
return false;
}

循环双链表的插入和删除操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 将结点s插入到结点p之后
bool InsertNextDNode(DNode *p, DNode *s){
s->next = p->next;
//循环双链表不用担心p结点的下一个结点为空
p->next->prior = s;
s->prior = p;
p->next = s;
}

// 删除p结点的后继结点
bool DeletNextDNode(DNode *p){
// 找到p的后继结点q
DNode *q =p->next;
//循环双链表不用担心q结点的下一个结点为空
p->next = q->next;
q->next->prior=p;
free(q);
return true;
}

参考自:https://blog.csdn.net/qq_55593227/article/details/123598044


数据结构之线性表代码
https://jimes.cn/2024/02/02/structure of data of list/
作者
Jimes
发布于
2024年2月2日
许可协议
\ No newline at end of file +数据结构之线性表代码 - 马锦的博客

数据结构之线性表代码

一,顺序表

1.1 顺序表的实现

静态实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define MaxSize 10 // 定义最大长度 

typedef struct {
int data[MaxSize]; // 使用静态的数组存放数据元素
int length; // 顺序表的当前长度
}SqList;

// 初始化顺序表
void InitList(SqList &L) {
L.length = 0; // 顺序表初始长度为0
}

int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表
return 0;
}

动态实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#define MaxSize 10 // 定义最大长度 
#define InitSize 10 // 顺序表的初始长度

typedef struct {
int *data; // 声明动态分配数组的指针
int MaxSize; // 顺序表的最大容量
int length; // 顺序表的当前长度
}SeqList;

// 初始化顺序表
void InitList(SeqList &L) {
// 用malloc函数申请一片连续的存储空间
L.data = (int *)malloc(InitSize * sizeof(int));
L.length = 0;
L.MaxSize = InitSize;
}

// 增加动态数组的长度 ,非重点
void IncreaseSize(SeqList &L, int len) {
int *p = L.data;
L.data = (int *)malloc((L.MaxSize+len) * sizeof(int));
for (int i = 0; i < L.length; i++)
L.data[i] = p[i]; // 将数据复制到新区域
L.MaxSize = L.MaxSize + len; // 顺序表最大长度增加len
free(p); // 释放原来的内存空间
}

int main() {
SeqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表
...
IncreaseSize(L, 5);
return 0;
}

malloc() 函数的作用:会申请一片存储空间,并返回存储空间第一个位置的地址,也就是该位置的指针。

1.2 顺序表的基本操作

插入:

1
2
3
4
5
6
7
8
9
10
11
12
// 在顺序表i位置插入e
bool ListInsert(SqList &L, int i, int e) {
if (i < 1 || i > L.length+1) // 判断i的范围是否有效
return false;
if (L.length >= MaxSize) // 判断存储空间是否已满
return false;
for (int j = L.length; j >= i; j--) // 将第i个元素之后的元素后移
L.data[j] = L.data[j-1];
L.data[i-1] = e; // 在位置i处放入e
L.length++; // 长度+1
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

删除:

1
2
3
4
5
6
7
8
9
10
// 删除顺序表i位置的数据并存入e
bool ListDelete(SqList &L, int i, int &e) {
if (i < 1 || i > L.length) // 判断i的范围是否有效
return false;
e = L.data[i-1]; // 将被删除的元素赋值给e
for (int j = i; j < L.length; j++) //将第i个位置后的元素前移
L.data[j-1] = L.data[j];
L.length--;
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

按位查找:

1
2
3
4
5
6
// 静态分配的按位查找
#define MaxSize 10

ElemType GetElem(SqList L, int i) {
return L.data[i-1];
}
1
2
3
4
5
6
// 动态分配的按位查找
#define InitSize 10

ElemType GetElem(SeqList L, int i) {
return L.data[i-1];
}

时间复杂度: O ( 1 )

按值查找:

1
2
3
4
5
6
7
// 查找第一个元素值为e的元素,并返回其位序 
int LocateElem(SqList L, ElemType e) {
for (int i = 0; i < L.length; i++)
if (L.data[i] == e)
return i+1; // 数组下标为i的元素值等于e,返回其位序i+1
return 0; // 没有查找到
}

在《数据结构》考研初试中,手写代码可以直接用“==”,无论 ElemType 是基本数据类型还是结构类型

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

二,单链表

2.1 单链表的实现

不带头结点的单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

//初始化一个空的单链表
bool InitList(LinkList &L){
L = NULL;//空表,暂时还没有任何结点
return true;
}

void test(){
LinkList L;//声明一个指向单链表的头指针
//初始化一个空表
InitList(L);
...
}

//判断单链表是否为空
bool Empty(LinkList L){
return (L==NULL)
}

带头结点的单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 初始化一个单链表(带头结点)
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));//分配一个头结点
if (L == NULL)//内存不足,分配失败
return false;
L->next = NULL;//头结点之后暂时还没有结点
return true;
}

void test(){
LinkList L;//声明一个指向单链表的头指针
//初始化一个空表
InitList(L);
...
}

//判断单链表是否为空
bool Empty(LinkList L){
if (L->next == NULL)
return true;
else
return false;
}

2.2 单链表的建立

尾插法建立单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 使用尾插法建立单链表L
LinkList List_TailInsert(LinkList &L){
int x;//设ElemType为整型int
L = (LinkList)malloc(sizeof(LNode));//建立头结点(初始化空表)
LNode *s, *r = L;//r为表尾指针
scanf("%d", &x);//输入要插入的结点的值
while(x!=9999){//输入9999表示结束
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;//r指针指向新的表尾结点
scanf("%d", &x);
}
r->next = NULL;//尾结点指针置空
return L;
}

时间复杂度:O ( n )

头插法建立单链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode));//建立头结点
L->next = NULL;//初始为空链表,这步很关键
scanf("%d", &x);//输入要插入的结点的值
while(x!=9999){//输入9999表结束
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
//将新结点插入表中,L为头指针
scanf("%d", &x);
}
return L;
}

头插法实现链表的逆置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 将链表L中的数据逆置并返回
LNode *Inverse(LNode *L){
LNode *p, *q;
p = L->next;//p指针指向第一个结点
L->next = NULL;//头结点置空
// 依次判断p结点中的数据并采用头插法插到L链表中
while (p != NULL){
q = p;
p = p->next;
q->next = L->next;
L->next = q;
}
return L;
}

2.3 单链表的基本操作

按位序插入(带头结点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return False;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p = L; //循环找到第i-1个结点
while(p!=NULL && j<i-1){ //如果i>lengh,p最后会等于NULL
p = p->next;
j++;
}
//p值为NULL说明i值不合法
if (p==NULL)
return false;
//在第i-1个结点后插入新结点
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
//将结点s连到p后
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

按位序插入(不带头结点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

//在第i个位置插入元素e
bool ListInsert(LinkList &L, int i, ElemType e){
//判断i的合法性
if(i<1)
return false;
//需要判断插入的位置是否是第1个
if(i==1){
LNode *s = (LNode *)malloc(size of(LNode));
s->data =e;
s->next =L;
L=s;//头指针指向新结点
return true;
}
//i>1的情况与带头结点一样,唯一区别是j的初始值为1
LNode *p;//指针p指向当前扫描到的结点
int j=1;//当前p指向的是第几个结点
p = L;
//循环找到第i-1个结点
while(p!=NULL && j<i-1){//如果i>lengh,p最后会等于NULL
p = p->next;
j++;
}
//p值为NULL说明i值不合法
if (p==NULL)
return false;
//在第i-1个结点后插入新结点
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

除非特别声明,否则之后的代码都默认为带头结点

指定结点的后插操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 在结点p后插入元素e
bool InsertNextNode(LNode *p, ElemType e){
if(p==NULL){
return false;
}
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}

// 按位序插入的函数中可以直接调用后插操作
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return False;
LNode *p;
//指针p指向当前扫描到的结点
int j=0;
//当前p指向的是第几个结点
p = L;
//循环找到第i-1个结点
while(p!=NULL && j<i-1){
//如果i>lengh, p最后会等于NULL
p = p->next;
j++;
}
return InsertNextNode(p, e)
}

时间复杂度:O ( 1 )

指定结点的前插操作:

如果传入头指针,就可以循环整个链表找到指定结点p的前驱结点q,再对q进行后插操作;
如果不传入头指针,可以在指定结点p后插入一个结点s,并交换两个结点所保存的数据,从而变相实现指定结点的前插操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 在结点p前插入元素e
bool InsertPriorNode(LNode *p, ElemType e){
if(p==NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
// 内存不足分配失败
if(s==NULL)
return false;
// 将s插入结点p之后
s->next = p->next;
p->next = s;
// 交换两个结点中的数据
s->data = p->data;
p->data = e;
return true;
}

时间复杂度:O ( 1 )

按位序删除:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct LNode{
ElemType data;
struct LNode *next;}LNode, *LinkList;

// 删除第i个结点并将其所保存的数据存入e
bool ListDelete(LinkList &L, int i, ElemType &e){
if(i<1)
return false;
LNode *p;//指针p指向当前扫描到的结点
int j=0;//当前p指向的是第几个结点
p = L;
//循环找到第i-1个结点
while(p!=NULL && j<i-1){
//如果i>lengh,p和p的后继结点会等于NULL
p = p->next;
j++;
}
if(p==NULL)
return false;
if(p->next == NULL)
return false;
//令q暂时保存被删除的结点
LNode *q = p->next;
e = q->data;
p->next = q->next;
free(q)
return true;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

删除指定结点:

如果传入头指针,就可以循环整个链表找到指定结点p的前驱结点q,再对p进行删除操作;
如果不传入头指针,可以把指定结点p的后继结点q删除,并使结点p保存结点q存储的数据,从而变相实现删除指定结点的操作。但是如果指定结点p没有后继结点,这么做会报错

1
2
3
4
5
6
7
8
9
10
// 删除指定结点p
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q = p->next;// 令q指向p的后继结点// 如果p是最后一个结点,则q指向NULL,继续执行就会报错
p->data = q->data;
p->next = q->next;
free(q);
return true;
}

时间复杂度:O ( 1 )

按位查找:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;

// 查找指定位序i的结点并返回
LNode * GetElem(LinkList L, int i){
if(i<0)
return NULL;
LNode *p;
int j=0;
p = L;
while(p!=NULL && j<i){
p = p->next;
j++;
}
return p;
}

// 封装后的插入操作,在第i个位置插入元素e,可以调用查询操作和后插操作
bool ListInsert(LinkList &L, int i, ElemType e){
if(i<1)
return False;
// 找到第i-1个元素
LNode *p = GetElem(L, i-1);
// 在p结点后插入元素e
return InsertNextNode(p, e)
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

按值查找:

1
2
3
4
5
6
7
8
9
// 查找数据域为e的结点指针,否则返回NULL
LNode * LocateElem(LinkList L, ElemType e){
LNode *P = L->next;
// 从第一个结点开始查找数据域为e的结点
while(p!=NULL && p->data != e){
p = p->next;
}
return p;
}

时间复杂度:

  • 最好时间复杂度:O ( 1 )
  • 最坏时间复杂度:O ( n )
  • 平均时间复杂度:O ( n )

计算单链表长度:

1
2
3
4
5
6
7
8
9
10
// 计算单链表的长度
int Length(LinkList L){
int len=0;//统计表长
LNode *p = L;
while(p->next != NULL){
p = p->next;
len++;
}
return len;
}

时间复杂度:O ( n )

三,双链表

双链表的初始化 (带头结点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef struct DNode{            //定义双链表结点类型
ElemType data; //数据域
struct DNode *prior, *next; //前驱和后继指针
}DNode, *DLinklist;

// 初始化双链表
bool InitDLinkList(Dlinklist &L){
L = (DNode *)malloc(sizeof(DNode));
if(L==NULL)
return false;
L->prior = NULL;//头结点的prior指针永远指向NULL
L->next = NULL;//头结点之后暂时还没有结点,置空
return true;
}

void testDLinkList(){
DLinklist L;
InitDLinkList(L);
...
}

// 判断双链表是否为空
bool Empty(DLinklist L){
if(L->next == NULL)
return true;
else
return false;
}

双链表的后插操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct DNode{
ElemType data;
struct DNode *prior, *next;
}DNode, *DLinklist;

// 将结点s插入到结点p之后
bool InsertNextDNode(DNode *p, DNode *s){
if(p==NULL || s==NULL)
return false;
s->next = p->next;
// 判断结点p之后是否有后继结点
if (p->next != NULL)
p->next->prior = s;
s->prior = p;
p->next = s;
return true;
}

双链表的前插操作、按位序插入操作都可以转换成后插操作

双链表的删除操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 删除p结点的后继结点
bool DeletNextDNode(DNode *p){
if(p==NULL)
return false;
// 找到p的后继结点q
DNode *q =p->next;
if(q==NULL)
return false;
p->next = q->next;
if(q->next != NULL)
q->next->prior=p;
free(q);
return true;
}

// 销毁一个双链表
bool DestoryList(DLinklist &L){
// 循环释放各个数据结点
while(L->next != NULL){
DeletNextDNode(L);
free(L);
// 头指针置空
L=NULL;
}
}

双链表的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 向后遍历
while(p!=NULL){
// 对结点p做相应处理
p = p->next;
}

// 向前遍历
while(p!=NULL){
// 对结点p做相应处理
p = p->prior;
}

// 跳过头结点的遍历
while(p->prior!=NULL){
//对结点p做相应处理
p = p->prior;
}

双链表不可随机存取,按位查找、按值查找操作都只能用遍历的方式实现。

四,循环链表

循环单链表的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typedef struct LNode{           
ElemType data;
struct LNode *next;
}DNode, *Linklist;

// 初始化循环单链表
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));
if(L==NULL)
return false;
// 最后一个结点的next指针指向头结点
L->next = L;
return true;
}

// 判断循环单链表是否为空
bool Empty(LinkList L){
if(L->next == L)
return true;
else
return false;
}

// 判断结点p是否为循环单链表的表尾结点
bool isTail(LinkList L, LNode *p){
if(p->next == L)
return true;
else
return false;
}

循环双链表的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
typedef struct DNode{            
ElemType data;
struct DNode *prior, *next;
}DNode, *DLinklist;

// 初始循环双链表
bool InitDLinkList(DLinklist &L){
L = (DNode *) malloc(sizeof(DNode));
if(L==NULL)
return false;
// 头结点的prior指针指向最后一个结点,最后一个结点的next指针指向头结点
L->prior = L;
L->next = L;
}

// 判断循环双链表是否为空
bool Empty(DLinklist L){
if(L->next == L)
return true;
else
return false;
}

// 判断结点p是否为循环双链表的表尾结点
bool isTail(DLinklist L, DNode *p){
if(p->next == L)
return true;
else
return false;
}

循环双链表的插入和删除操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 将结点s插入到结点p之后
bool InsertNextDNode(DNode *p, DNode *s){
s->next = p->next;
//循环双链表不用担心p结点的下一个结点为空
p->next->prior = s;
s->prior = p;
p->next = s;
}

// 删除p结点的后继结点
bool DeletNextDNode(DNode *p){
// 找到p的后继结点q
DNode *q =p->next;
//循环双链表不用担心q结点的下一个结点为空
p->next = q->next;
q->next->prior=p;
free(q);
return true;
}

参考自:https://blog.csdn.net/qq_55593227/article/details/123598044


数据结构之线性表代码
https://jimes.cn/2024/02/02/structure of data of list/
作者
Jimes
发布于
2024年2月2日
许可协议
+ + \ No newline at end of file diff --git a/2024/02/03/structure of data of stack and queue/index.html b/2024/02/03/structure of data of stack and queue/index.html index 3dec8f1..5e692e7 100644 --- a/2024/02/03/structure of data of stack and queue/index.html +++ b/2024/02/03/structure of data of stack and queue/index.html @@ -1 +1,14 @@ -数据结构之栈与队列代码 - 马锦的博客

数据结构之栈与队列代码

一,顺序栈

顺序栈的定义:

1
2
3
4
5
#define MaxSize 10           //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶元素
}SqStack;

顺序栈的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;

// 初始化栈
void InitStack(SqStack &S){
S.top = -1;//初始化栈顶指针
}

// 判断栈是否为空
bool StackEmpty(SqStack S){
if(S.top == -1)
return true;
else
return false;
}

入栈出栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 新元素进栈
bool Push(SqStack &S, ElemType x){
// 判断栈是否已满
if(S.top == MaxSize - 1)
return false;
S.data[++S.top] = x;
return true;
}

// 出栈
bool Pop(SqStack &x, ElemType &x){
// 判断栈是否为空
if(S.top == -1)
return false;
x = S.data[S.top--];
return true;
}

读取栈顶元素:

1
2
3
4
5
6
7
// 读栈顶元素
bool GetTop(SqStack S, ElemType &x){
if(S.top == -1)
return false;
x = S.data[S.top];
return true;
}

共享栈(两个栈共享同一片空间):

1
2
3
4
5
6
7
8
9
10
11
12
#define MaxSize 10      //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize];//静态数组存放栈中元素
int top0; //0号栈栈顶指针
int top1; //1号栈栈顶指针
}ShStack;

// 初始化栈
void InitSqStack(ShStack &S){
S.top0 = -1;
S.top1 = MaxSize;
}

二,链栈

链栈的定义:

1
2
3
4
5
6
7
8
typedef struct Linknode{
ElemType data;//数据域
Linknode *next;//指针域
}Linknode,*LiStack;

void testStack(){
LiStack L;//声明一个链栈
}

链栈的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct Linknode{
ElemType data;
Linknode *next;
}Linknode,*LiStack;

// 初始化栈
bool InitStack(LiStack &L){
L = (Linknode *)malloc(sizeof(Linknode));
if(L == NULL)
return false;
L->next = NULL;
return true;
}

// 判断栈是否为空
bool isEmpty(LiStack &L){
if(L->next == NULL)
return true;
else
return false;
}

入栈出栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 新元素入栈
bool pushStack(LiStack &L,ElemType x){
Linknode *s = (Linknode *)malloc(sizeof(Linknode));
if(s == NULL)
return false;
s->data = x;
// 头插法
s->next = L->next;
L->next = s;
return true;
}

// 出栈
bool popStack(LiStack &L, int &x){
// 栈空不能出栈
if(L->next == NULL)
return false;
Linknode *s = L->next;
x = s->data;
L->next = s->next;
free(s);
return true;
}

三,顺序队列

顺序队列的定义:

1
2
3
4
5
6
7
8
9
#define MaxSize 10;//定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize];//用静态数组存放队列元素
int front, rear; //队头指针和队尾指针
}SqQueue;

void test{
SqQueue Q;//声明一个队列
}

顺序队列的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define MaxSize 10;
typedef struct{
ElemType data[MaxSize];
int front, rear;
}SqQueue;

// 初始化队列
void InitQueue(SqQueue &Q){
// 初始化时,队头、队尾指针指向0
// 队尾指针指向的是即将插入数据的数组下标
// 队头指针指向的是队头元素的数组下标
Q.rear = Q.front = 0;
}

// 判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.rear == Q.front)
return true;
else
return false;
}

入队出队(循环队列):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 新元素入队
bool EnQueue(SqQueue &Q, ElemType x){
// 如果队列已满直接返回
if((Q.rear+1)%MaxSize == Q.front)//牺牲一个单元区分队空和队满
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear+1)%MaxSize;
return true;
}

// 出队
bool DeQueue(SqQueue &Q, ElemType &x){
// 如果队列为空直接返回
if(Q.rear == Q.front)
return false;
x = Q.data[Q.front];
Q.front = (Q.front+1)%MaxSize;
return true;
}

获得队头元素:

1
2
3
4
5
6
7
// 获取队头元素并存入x
bool GetHead(SqQueue &Q, ElemType &x){
if(Q.rear == Q.front)
return false;
x = Q.data[Q.front];
return true;
}

四,链队列

链队列的定义:

1
2
3
4
5
6
7
8
9
10
11
// 链式队列结点
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}

// 链式队列
typedef struct{
// 头指针和尾指针
LinkNode *front, *rear;
}LinkQueue;

链队列的初始化(带头结点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;

typedef struct{
LinkNode *front, *rear;
}LinkQueue;

// 初始化队列
void InitQueue(LinkQueue &Q){
// 初始化时,front、rear都指向头结点
Q.front = Q.rear = (LinkNode *)malloc(sizeof(LinkNode));
Q.front -> next = NULL;
}

// 判断队列是否为空
bool IsEmpty(LinkQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}

入队出队:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 新元素入队
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;
}

// 队头元素出队
bool DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == Q.rear)
return false;
LinkNode *p = Q.front->next;
x = p->data;
Q.front->next = p->next;
// 如果p是最后一个结点,则将队头指针也指向NULL
if(Q.rear == p)
Q.rear = Q.front;
free(p);
return true;
}

以上是带头结点的链队列,下面是不带头结点的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;

typedef struct{
LinkNode *front, *rear;
}LinkQueue;

// 初始化队列
void InitQueue(LinkQueue &Q){
// 不带头结点的链队列初始化,头指针和尾指针都指向NULL
Q.front = NULL;
Q.rear = NULL;
}

// 判断队列是否为空
bool IsEmpty(LinkQueue Q){
if(Q.front == NULL)
return true;
else
return false;
}

// 新元素入队
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
// 第一个元素入队时需要特别处理
if(Q.front == NULL){
Q.front = s;
Q.rear = s;
}else{
Q.rear->next = s;
Q.rear = s;
}
}

//队头元素出队
bool DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == NULL)
return false;
LinkNode *s = Q.front;
x = s->data;
if(Q.front == Q.rear){
Q.front = Q.rear = NULL;
}else{
Q.front = Q.front->next;
}
free(s);
return true;
}

参考自:https://blog.csdn.net/qq_55593227/article/details/123598044


数据结构之栈与队列代码
https://jimes.cn/2024/02/03/structure of data of stack and queue/
作者
Jimes
发布于
2024年2月3日
许可协议
\ No newline at end of file +数据结构之栈与队列代码 - 马锦的博客

数据结构之栈与队列代码

一,顺序栈

顺序栈的定义:

1
2
3
4
5
#define MaxSize 10           //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶元素
}SqStack;

顺序栈的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;

// 初始化栈
void InitStack(SqStack &S){
S.top = -1;//初始化栈顶指针
}

// 判断栈是否为空
bool StackEmpty(SqStack S){
if(S.top == -1)
return true;
else
return false;
}

入栈出栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 新元素进栈
bool Push(SqStack &S, ElemType x){
// 判断栈是否已满
if(S.top == MaxSize - 1)
return false;
S.data[++S.top] = x;
return true;
}

// 出栈
bool Pop(SqStack &x, ElemType &x){
// 判断栈是否为空
if(S.top == -1)
return false;
x = S.data[S.top--];
return true;
}

读取栈顶元素:

1
2
3
4
5
6
7
// 读栈顶元素
bool GetTop(SqStack S, ElemType &x){
if(S.top == -1)
return false;
x = S.data[S.top];
return true;
}

共享栈(两个栈共享同一片空间):

1
2
3
4
5
6
7
8
9
10
11
12
#define MaxSize 10      //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize];//静态数组存放栈中元素
int top0; //0号栈栈顶指针
int top1; //1号栈栈顶指针
}ShStack;

// 初始化栈
void InitSqStack(ShStack &S){
S.top0 = -1;
S.top1 = MaxSize;
}

二,链栈

链栈的定义:

1
2
3
4
5
6
7
8
typedef struct Linknode{
ElemType data;//数据域
Linknode *next;//指针域
}Linknode,*LiStack;

void testStack(){
LiStack L;//声明一个链栈
}

链栈的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct Linknode{
ElemType data;
Linknode *next;
}Linknode,*LiStack;

// 初始化栈
bool InitStack(LiStack &L){
L = (Linknode *)malloc(sizeof(Linknode));
if(L == NULL)
return false;
L->next = NULL;
return true;
}

// 判断栈是否为空
bool isEmpty(LiStack &L){
if(L->next == NULL)
return true;
else
return false;
}

入栈出栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 新元素入栈
bool pushStack(LiStack &L,ElemType x){
Linknode *s = (Linknode *)malloc(sizeof(Linknode));
if(s == NULL)
return false;
s->data = x;
// 头插法
s->next = L->next;
L->next = s;
return true;
}

// 出栈
bool popStack(LiStack &L, int &x){
// 栈空不能出栈
if(L->next == NULL)
return false;
Linknode *s = L->next;
x = s->data;
L->next = s->next;
free(s);
return true;
}

三,顺序队列

顺序队列的定义:

1
2
3
4
5
6
7
8
9
#define MaxSize 10;//定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize];//用静态数组存放队列元素
int front, rear; //队头指针和队尾指针
}SqQueue;

void test{
SqQueue Q;//声明一个队列
}

顺序队列的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define MaxSize 10;
typedef struct{
ElemType data[MaxSize];
int front, rear;
}SqQueue;

// 初始化队列
void InitQueue(SqQueue &Q){
// 初始化时,队头、队尾指针指向0
// 队尾指针指向的是即将插入数据的数组下标
// 队头指针指向的是队头元素的数组下标
Q.rear = Q.front = 0;
}

// 判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.rear == Q.front)
return true;
else
return false;
}

入队出队(循环队列):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 新元素入队
bool EnQueue(SqQueue &Q, ElemType x){
// 如果队列已满直接返回
if((Q.rear+1)%MaxSize == Q.front)//牺牲一个单元区分队空和队满
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear+1)%MaxSize;
return true;
}

// 出队
bool DeQueue(SqQueue &Q, ElemType &x){
// 如果队列为空直接返回
if(Q.rear == Q.front)
return false;
x = Q.data[Q.front];
Q.front = (Q.front+1)%MaxSize;
return true;
}

获得队头元素:

1
2
3
4
5
6
7
// 获取队头元素并存入x
bool GetHead(SqQueue &Q, ElemType &x){
if(Q.rear == Q.front)
return false;
x = Q.data[Q.front];
return true;
}

四,链队列

链队列的定义:

1
2
3
4
5
6
7
8
9
10
11
// 链式队列结点
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}

// 链式队列
typedef struct{
// 头指针和尾指针
LinkNode *front, *rear;
}LinkQueue;

链队列的初始化(带头结点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;

typedef struct{
LinkNode *front, *rear;
}LinkQueue;

// 初始化队列
void InitQueue(LinkQueue &Q){
// 初始化时,front、rear都指向头结点
Q.front = Q.rear = (LinkNode *)malloc(sizeof(LinkNode));
Q.front -> next = NULL;
}

// 判断队列是否为空
bool IsEmpty(LinkQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}

入队出队:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 新元素入队
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;
}

// 队头元素出队
bool DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == Q.rear)
return false;
LinkNode *p = Q.front->next;
x = p->data;
Q.front->next = p->next;
// 如果p是最后一个结点,则将队头指针也指向NULL
if(Q.rear == p)
Q.rear = Q.front;
free(p);
return true;
}

以上是带头结点的链队列,下面是不带头结点的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;

typedef struct{
LinkNode *front, *rear;
}LinkQueue;

// 初始化队列
void InitQueue(LinkQueue &Q){
// 不带头结点的链队列初始化,头指针和尾指针都指向NULL
Q.front = NULL;
Q.rear = NULL;
}

// 判断队列是否为空
bool IsEmpty(LinkQueue Q){
if(Q.front == NULL)
return true;
else
return false;
}

// 新元素入队
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
// 第一个元素入队时需要特别处理
if(Q.front == NULL){
Q.front = s;
Q.rear = s;
}else{
Q.rear->next = s;
Q.rear = s;
}
}

//队头元素出队
bool DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == NULL)
return false;
LinkNode *s = Q.front;
x = s->data;
if(Q.front == Q.rear){
Q.front = Q.rear = NULL;
}else{
Q.front = Q.front->next;
}
free(s);
return true;
}

参考自:https://blog.csdn.net/qq_55593227/article/details/123598044


数据结构之栈与队列代码
https://jimes.cn/2024/02/03/structure of data of stack and queue/
作者
Jimes
发布于
2024年2月3日
许可协议
+ + \ No newline at end of file diff --git "a/2024/07/21/\347\224\237\346\255\273\347\213\231\345\207\2732\345\207\200\345\214\226\350\241\214\345\212\250\346\214\202\346\234\272\350\204\232\346\234\254/index.html" "b/2024/07/21/\347\224\237\346\255\273\347\213\231\345\207\2732\345\207\200\345\214\226\350\241\214\345\212\250\346\214\202\346\234\272\350\204\232\346\234\254/index.html" index 123ae75..8218477 100644 --- "a/2024/07/21/\347\224\237\346\255\273\347\213\231\345\207\2732\345\207\200\345\214\226\350\241\214\345\212\250\346\214\202\346\234\272\350\204\232\346\234\254/index.html" +++ "b/2024/07/21/\347\224\237\346\255\273\347\213\231\345\207\2732\345\207\200\345\214\226\350\241\214\345\212\250\346\214\202\346\234\272\350\204\232\346\234\254/index.html" @@ -1 +1,14 @@ -生死狙击2净化行动挂机脚本 - 马锦的博客

生死狙击2净化行动挂机脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import pyautogui
import pydirectinput
import time
import os
import sys
pyautogui.PAUSE = 0
#适用于净化行动,关闭自动匹配队友,开启单人匹配,在开始匹配页面运行程序。
######### 以管理员身份运行!!!! ###########
# 获取图片的绝对路径
def get_resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
#局内动作循环
def repeat_keys(keys):
try:
a = time.time()
bb = time.time()
while a-bb+5000>0:
for key in keys:
pyautogui.keyDown(key)
time.sleep(1)
pyautogui.keyUp(key)
time.sleep(9)
bb = time.time()
pyautogui.press('esc')
except KeyboardInterrupt:
print("Stopped by user")
#检测图片
def identify_picture(a):
left, top, width, height = pyautogui.locateOnScreen(get_resource_path(a),confidence=0.9,grayscale=True) # 寻找图片
center = pyautogui.center((left, top, width, height)) # 寻找图片的中心
print('开始',center)
pydirectinput.moveTo(center[0],center[1])
pydirectinput.click()
time.sleep(10)
# 4:3比例 + 无边框窗口
while True:
try:
identify_picture('img\sta1.png') #检测开始匹配
except TypeError:
try:
identify_picture('img\\bac.png') #检测返回大厅
except TypeError:
try:
identify_picture('img\\img.png') #检测准备完毕
repeat_keys(['w', 'a', 's', 'd']) #局内动作,防止强退
except TypeError:
try:
identify_picture('img\\img_1.png') #检测返回大厅(出错情况)
except TypeError:
try:
identify_picture('img\\img_2.png') #检测确定(出错情况)
except TypeError:
try:
identify_picture('img\\img_3.png') #检测点击空白处关闭(出错情况)
except TypeError:
print('无')
time.sleep(2)

生死狙击2净化行动挂机脚本
https://jimes.cn/2024/07/21/生死狙击2净化行动挂机脚本/
作者
Jimes
发布于
2024年7月21日
许可协议
\ No newline at end of file +生死狙击2净化行动挂机脚本 - 马锦的博客

生死狙击2净化行动挂机脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import pyautogui
import pydirectinput
import time
import os
import sys
pyautogui.PAUSE = 0
#适用于净化行动,关闭自动匹配队友,开启单人匹配,在开始匹配页面运行程序。
######### 以管理员身份运行!!!! ###########
# 获取图片的绝对路径
def get_resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
#局内动作循环
def repeat_keys(keys):
try:
a = time.time()
bb = time.time()
while a-bb+5000>0:
for key in keys:
pyautogui.keyDown(key)
time.sleep(1)
pyautogui.keyUp(key)
time.sleep(9)
bb = time.time()
pyautogui.press('esc')
except KeyboardInterrupt:
print("Stopped by user")
#检测图片
def identify_picture(a):
left, top, width, height = pyautogui.locateOnScreen(get_resource_path(a),confidence=0.9,grayscale=True) # 寻找图片
center = pyautogui.center((left, top, width, height)) # 寻找图片的中心
print('开始',center)
pydirectinput.moveTo(center[0],center[1])
pydirectinput.click()
time.sleep(10)
# 4:3比例 + 无边框窗口
while True:
try:
identify_picture('img\sta1.png') #检测开始匹配
except TypeError:
try:
identify_picture('img\\bac.png') #检测返回大厅
except TypeError:
try:
identify_picture('img\\img.png') #检测准备完毕
repeat_keys(['w', 'a', 's', 'd']) #局内动作,防止强退
except TypeError:
try:
identify_picture('img\\img_1.png') #检测返回大厅(出错情况)
except TypeError:
try:
identify_picture('img\\img_2.png') #检测确定(出错情况)
except TypeError:
try:
identify_picture('img\\img_3.png') #检测点击空白处关闭(出错情况)
except TypeError:
print('无')
time.sleep(2)

生死狙击2净化行动挂机脚本
https://jimes.cn/2024/07/21/生死狙击2净化行动挂机脚本/
作者
Jimes
发布于
2024年7月21日
许可协议
+ + \ No newline at end of file diff --git a/404.html b/404.html index b8da928..3124518 100644 --- a/404.html +++ b/404.html @@ -1 +1,14 @@ -页面不存在 - 马锦的博客
\ No newline at end of file +页面不存在 - 马锦的博客
+ + \ No newline at end of file diff --git a/about/index.html b/about/index.html index 3bc81c2..151c75c 100644 --- a/about/index.html +++ b/about/index.html @@ -1 +1,14 @@ -关于 - 马锦的博客
\ No newline at end of file +关于 - 马锦的博客
+ + \ No newline at end of file diff --git a/archives/2024/01/index.html b/archives/2024/01/index.html index 5a2e4ed..d6f3ada 100644 --- a/archives/2024/01/index.html +++ b/archives/2024/01/index.html @@ -1 +1,14 @@ -归档 - 马锦的博客
\ No newline at end of file +归档 - 马锦的博客
+ + \ No newline at end of file diff --git a/archives/2024/02/index.html b/archives/2024/02/index.html index 77ace98..0fb71f4 100644 --- a/archives/2024/02/index.html +++ b/archives/2024/02/index.html @@ -1 +1,14 @@ -归档 - 马锦的博客
\ No newline at end of file +归档 - 马锦的博客
+ + \ No newline at end of file diff --git a/archives/2024/07/index.html b/archives/2024/07/index.html index 547c345..1b834e8 100644 --- a/archives/2024/07/index.html +++ b/archives/2024/07/index.html @@ -1 +1,14 @@ -归档 - 马锦的博客
\ No newline at end of file +归档 - 马锦的博客
+ + \ No newline at end of file diff --git a/archives/2024/index.html b/archives/2024/index.html index 960ded2..3d6dfe8 100644 --- a/archives/2024/index.html +++ b/archives/2024/index.html @@ -1 +1,14 @@ -归档 - 马锦的博客
\ No newline at end of file +归档 - 马锦的博客
+ + \ No newline at end of file diff --git a/archives/index.html b/archives/index.html index 1964ad6..35c26d9 100644 --- a/archives/index.html +++ b/archives/index.html @@ -1 +1,14 @@ -归档 - 马锦的博客
\ No newline at end of file +归档 - 马锦的博客
+ + \ No newline at end of file diff --git a/categories/index.html b/categories/index.html index 46d1fe3..1deb9c9 100644 --- a/categories/index.html +++ b/categories/index.html @@ -1 +1,14 @@ -分类 - 马锦的博客
\ No newline at end of file +分类 - 马锦的博客
+ + \ No newline at end of file diff --git "a/categories/\344\272\272\345\267\245\346\231\272\350\203\275/index.html" "b/categories/\344\272\272\345\267\245\346\231\272\350\203\275/index.html" index b64dffe..ef9aacf 100644 --- "a/categories/\344\272\272\345\267\245\346\231\272\350\203\275/index.html" +++ "b/categories/\344\272\272\345\267\245\346\231\272\350\203\275/index.html" @@ -1 +1,14 @@ -分类 - 人工智能 - 马锦的博客

共计 1 篇文章


2024

人工智能学习导航
\ No newline at end of file +分类 - 人工智能 - 马锦的博客

共计 1 篇文章


2024

人工智能学习导航
+ + \ No newline at end of file diff --git "a/categories/\345\237\272\347\241\200\345\267\245\345\205\267/index.html" "b/categories/\345\237\272\347\241\200\345\267\245\345\205\267/index.html" index 2ff5973..c27b008 100644 --- "a/categories/\345\237\272\347\241\200\345\267\245\345\205\267/index.html" +++ "b/categories/\345\237\272\347\241\200\345\267\245\345\205\267/index.html" @@ -1 +1,14 @@ -分类 - 基础工具 - 马锦的博客
\ No newline at end of file +分类 - 基础工具 - 马锦的博客
+ + \ No newline at end of file diff --git "a/categories/\346\270\270\346\210\217/index.html" "b/categories/\346\270\270\346\210\217/index.html" index 7a19d50..e3ac8b5 100644 --- "a/categories/\346\270\270\346\210\217/index.html" +++ "b/categories/\346\270\270\346\210\217/index.html" @@ -1 +1,14 @@ -分类 - 游戏 - 马锦的博客
\ No newline at end of file +分类 - 游戏 - 马锦的博客
+ + \ No newline at end of file diff --git "a/categories/\346\270\270\346\210\217/\350\207\252\345\212\250\345\214\226/index.html" "b/categories/\346\270\270\346\210\217/\350\207\252\345\212\250\345\214\226/index.html" index 0dfde33..b875804 100644 --- "a/categories/\346\270\270\346\210\217/\350\207\252\345\212\250\345\214\226/index.html" +++ "b/categories/\346\270\270\346\210\217/\350\207\252\345\212\250\345\214\226/index.html" @@ -1 +1,14 @@ -分类 - 自动化 - 马锦的博客
\ No newline at end of file +分类 - 自动化 - 马锦的博客
+ + \ No newline at end of file diff --git "a/categories/\350\200\203\347\240\224408/index.html" "b/categories/\350\200\203\347\240\224408/index.html" index 14a2350..a4bc033 100644 --- "a/categories/\350\200\203\347\240\224408/index.html" +++ "b/categories/\350\200\203\347\240\224408/index.html" @@ -1 +1,14 @@ -分类 - 考研408 - 马锦的博客
\ No newline at end of file +分类 - 考研408 - 马锦的博客
+ + \ No newline at end of file diff --git a/index.html b/index.html index 52390d9..363add2 100644 --- a/index.html +++ b/index.html @@ -1 +1,14 @@ -马锦的博客
\ No newline at end of file +马锦的博客
+ + \ No newline at end of file diff --git a/links/index.html b/links/index.html index c17acc1..81c8b45 100644 --- a/links/index.html +++ b/links/index.html @@ -1 +1,14 @@ -友链 - 马锦的博客
\ No newline at end of file +友链 - 马锦的博客
+ + \ No newline at end of file diff --git a/sw-register.js b/sw-register.js index 405be3b..1563204 100644 --- a/sw-register.js +++ b/sw-register.js @@ -1 +1 @@ -navigator.serviceWorker&&navigator.serviceWorker.register('/sw.js?v=20240722133129').then(function(){navigator.serviceWorker.addEventListener('message',function(a){if('sw.update'===a.data){let a=document.querySelector('meta[name=theme-color]'),b=document.createElement('div');a&&(a.content='#000'),b.innerHTML='

\u64cd\u4f5c\u901a\u77e5

\u5df2\u66f4\u65b0\u6700\u65b0\u7248\u672c\uff08\u5237\u65b0\u751f\u6548\uff09
×
',document.body.appendChild(b),setTimeout(function(){document.getElementById('app-refresh').className+=' app-refresh-show'},16)}})}); \ No newline at end of file +navigator.serviceWorker&&navigator.serviceWorker.register('/sw.js?v=20240722152700').then(function(){navigator.serviceWorker.addEventListener('message',function(a){if('sw.update'===a.data){let a=document.querySelector('meta[name=theme-color]'),b=document.createElement('div');a&&(a.content='#000'),b.innerHTML='

\u64cd\u4f5c\u901a\u77e5

\u5df2\u66f4\u65b0\u6700\u65b0\u7248\u672c\uff08\u5237\u65b0\u751f\u6548\uff09
×
',document.body.appendChild(b),setTimeout(function(){document.getElementById('app-refresh').className+=' app-refresh-show'},16)}})}); \ No newline at end of file diff --git a/sw.js b/sw.js index 0ec1f5d..3933a6f 100644 --- a/sw.js +++ b/sw.js @@ -10,7 +10,7 @@ 'use strict'; -var precacheConfig = [["/2024/01/09/GitHub desktop基本用法/2023-05-07_232823.png","c24df821a6497444e71b2243e0577a9a"],["/2024/01/09/GitHub desktop基本用法/Untitled 1.png","2fa248a8f262c8636a07d3bd06dcc1fe"],["/2024/01/09/GitHub desktop基本用法/Untitled 10.png","c2154d964d2e468589b86bef5f35d53a"],["/2024/01/09/GitHub desktop基本用法/Untitled 11.png","abda8e93832cdb4fb8b0e6341c8d031f"],["/2024/01/09/GitHub desktop基本用法/Untitled 12.png","3505440efe0f7c43537137fd83adeb14"],["/2024/01/09/GitHub desktop基本用法/Untitled 13.png","46f19d6ccf828fd50d1317069a3aa2bb"],["/2024/01/09/GitHub desktop基本用法/Untitled 14.png","c7d61ce5820b53b7cfb746674160f9c5"],["/2024/01/09/GitHub desktop基本用法/Untitled 15.png","1c74bd4c3c479c6cbb717b5ab7ba9380"],["/2024/01/09/GitHub desktop基本用法/Untitled 16.png","17d74c538216b387e59724648a311cf9"],["/2024/01/09/GitHub desktop基本用法/Untitled 17.png","e61d189ea48bf0684d3c6330cae5b66e"],["/2024/01/09/GitHub desktop基本用法/Untitled 18.png","a0f26d2c02b09e6f98a49b4ed5e92990"],["/2024/01/09/GitHub desktop基本用法/Untitled 19.png","655dace5a204d04f04bb771c1f78f202"],["/2024/01/09/GitHub desktop基本用法/Untitled 2.png","326f9c7a13fe45ec249f127fc0380ccd"],["/2024/01/09/GitHub desktop基本用法/Untitled 20.png","68f746a0060ea6c081d1bf2c1496fb2f"],["/2024/01/09/GitHub desktop基本用法/Untitled 21.png","b1e5ea352441a541703f9d2867bc3841"],["/2024/01/09/GitHub desktop基本用法/Untitled 22.png","9197489c29212235b23d03aaafc12169"],["/2024/01/09/GitHub desktop基本用法/Untitled 23.png","f13175ce125954d6db5235205f48d978"],["/2024/01/09/GitHub desktop基本用法/Untitled 24.png","43e23660e25d8aa2e044c40c459cd400"],["/2024/01/09/GitHub desktop基本用法/Untitled 25.png","138b3364053bb65add68db6669f5d636"],["/2024/01/09/GitHub desktop基本用法/Untitled 26.png","426824e5d019a894a527b700abe629de"],["/2024/01/09/GitHub desktop基本用法/Untitled 27.png","6fcb131534b72e9365601b15cffa56bb"],["/2024/01/09/GitHub desktop基本用法/Untitled 3.png","354fa66f304720bdef613d8096574e32"],["/2024/01/09/GitHub desktop基本用法/Untitled 4.png","cd69f961522f00c1fac975902d60823d"],["/2024/01/09/GitHub desktop基本用法/Untitled 5.png","56c7f45017b1c73b44fe11be74a3b923"],["/2024/01/09/GitHub desktop基本用法/Untitled 6.png","4830b6f9dec4491262ec4335c953bb16"],["/2024/01/09/GitHub desktop基本用法/Untitled 7.png","50613175b6820d882c6b95df34780461"],["/2024/01/09/GitHub desktop基本用法/Untitled 8.png","d8513c20ac045674ba216bca64a1060a"],["/2024/01/09/GitHub desktop基本用法/Untitled 9.png","4305232b7f50b2c39bebbdcf89f10117"],["/2024/01/09/GitHub desktop基本用法/Untitled.png","af1264ba3284f0a578c35ca704f2ab4f"],["/2024/01/09/GitHub desktop基本用法/index.html","c6862d55cf4cc5e0cbd12ce01097a36d"],["/2024/01/10/人工智能学习导航/index.html","298b976ab331ef38952b011396e40afe"],["/2024/01/12/python程序带图片等资源打包/index.html","d22388ef79db02d7fe547f979c3043c5"],["/2024/02/02/structure of data of list/0.png","2b028709516f6023ac66007787041a0d"],["/2024/02/02/structure of data of list/1.png","1f00a1194c816c72c1ca43c2c657b95c"],["/2024/02/02/structure of data of list/2.png","8e50124b699c63ef75e46c88c180afb7"],["/2024/02/02/structure of data of list/index.html","6f89875d6bb1ae307f5e61870bdbc791"],["/2024/02/03/structure of data of stack and queue/index.html","9c6952d7dd5cd352e4c9eb8c77a83a9c"],["/2024/07/21/生死狙击2净化行动挂机脚本/index.html","4e5bdc505a538cef59efea670e53d6c5"],["/404.html","444b019d187370320118024f5e80c45b"],["/about/index.html","c1001f27b75606ff7c391f72e3e66fa5"],["/archives/2024/01/index.html","e6638d139bf710e66b41a51ce472f1b5"],["/archives/2024/02/index.html","3b7889e02546614ff5b108166828bceb"],["/archives/2024/07/index.html","60593f367380a21b233188b545d374ff"],["/archives/2024/index.html","daf63d78a7f81101ab8617fecc8e600b"],["/archives/index.html","76b8eecb0528822989926dd0df852ba8"],["/categories/index.html","eda425873883f075eb006e8033a74173"],["/categories/人工智能/index.html","88082c9dcdae84fe3f5efd1563272998"],["/categories/基础工具/index.html","b311f389eb09982a3cd17d2026e2e807"],["/categories/游戏/index.html","e506a2ef37f484c672c61354ab5081a4"],["/categories/游戏/自动化/index.html","0c90d7cf7116874adc636bdaf20a58bb"],["/categories/考研408/index.html","72cafb7017ddceedbdbb11256a5c4752"],["/css/gitalk.css","1573fd650b11482f9dd295ed4af024c5"],["/css/highlight-dark.css","fa6d808c194fbe83fa70b5193d0ec41d"],["/css/highlight.css","207b917e3c65ff58f49935eb708c3a5d"],["/css/main.css","7f767f8cc752f996cd6fd8993725180e"],["/img/avatar.png","e4020cb9bc27a52f406fa41c882f5cd1"],["/img/default.png","68977cd063e5d182b3a43614be3d98d8"],["/img/fluid.png","4aed91411d3b02af426592260f4b7b12"],["/img/loading.gif","93e33d89a8cbe54ec945235d25af5607"],["/img/police_beian.png","b769e8dfde5660239317ed60758dba13"],["/index.html","cd16b1336b610bceb3b583168ad66269"],["/js/boot.js","7683fab2fc9d03a3a659aa956b3a54e8"],["/js/color-schema.js","5e4105d10638e64b40820fa28567d0d5"],["/js/events.js","734c9d1a9b78947e2e2e2d8b88c5920b"],["/js/img-lazyload.js","fab30a410e5f490fce3f977a6936a714"],["/js/leancloud.js","fb4a815ccdb5d851d00561dbb62251c4"],["/js/local-search.js","9dc47a0b7b6bacfd16541c9b2b5b6bc5"],["/js/plugins.js","6c10bee3f659ca91b534bf4a81d62f1e"],["/js/utils.js","f7ce9014de1cd7358eeb3aba81c8efe2"],["/links/index.html","684c5f7b398d23d0570d1057315d37a1"],["/sw-register.js","a04f9750a353e687262fdf65d126f094"],["/tags/index.html","47ca4cce3567ee28fcb2fcbfdd62294f"]]; +var precacheConfig = []; var cacheName = 'sw-precache-v3--' + (self.registration ? self.registration.scope : ''); var firstRegister = 1; // 默认1是首次安装SW, 0是SW更新 diff --git a/tags/index.html b/tags/index.html index ab66a9a..47bb513 100644 --- a/tags/index.html +++ b/tags/index.html @@ -1 +1,14 @@ -标签 - 马锦的博客
\ No newline at end of file +标签 - 马锦的博客
+ + \ No newline at end of file