当前位置: 首页 > news >正文

【海贼王的数据航海:利用数据结构成为数据海洋的霸主】链表—双向链表

目录

往期

1 -> 带头+双向+循环链表(双链表)

1.1 -> 接口声明

1.2 -> 接口实现

1.2.1 -> 双向链表初始化

1.2.2 -> 动态申请一个结点

1.2.3 -> 双向链表销毁

1.2.4 -> 双向链表打印

1.2.5 -> 双向链表判空

1.2.6 -> 双向链表尾插

1.2.7 -> 双向链表尾删

1.2.8 -> 双向链表头插

1.2.9 -> 双向链表头删

1.2.10 -> 双向链表查找

1.2.11 ->  双向链表在pos的前面进行插入

1.2.12 -> 双向链表删除pos位置的节点

2 -> 顺序表和链表的区别

3 -> 完整代码

3.1 -> List.c

3.2 -> List.h

3.3 -> Test.c


往期

链表-单链表

1 -> 带头+双向+循环链表(双链表)

1.1 -> 接口声明

#pragma once#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>// 带头+双向+循环链表增删查改实现
typedef int LTDataType;typedef struct LTNode
{LTDataType data;struct LTNode* next;struct LTNode* prev;
}LTNode;// 双向链表初始化
LTNode* LTInit();// 动态申请一个结点
LTNode* BuyLTNode(LTDataType x);// 双向链表销毁
void LTDestory(LTNode* phead);// 双向链表打印
void LTPrint(LTNode* phead);// 双向链表判空
bool LTEmpty(LTNode* phead);// 双向链表尾插
void LTPushBack(LTNode* phead, LTDataType x);// 双向链表尾删
void LTPopBack(LTNode* phead);// 双向链表头插
void LTPushFront(LTNode* phead, LTDataType x);// 双向链表头删
void LTPopFront(LTNode* phead);// 双向链表查找
LTNode* LTFind(LTNode* phead, LTDataType x);// 双向链表在pos的前面进行插入
void LTInsert(LTNode* pos, LTDataType x);// 双向链表删除pos位置的节点
void LTErase(LTNode* pos);

1.2 -> 接口实现

1.2.1 -> 双向链表初始化

// 双向链表初始化
LTNode* LTInit()
{LTNode* phead = BuyLTNode(-1);phead->next = phead;phead->prev = phead;return phead;
}

1.2.2 -> 动态申请一个结点

// 动态申请一个结点
LTNode* BuyLTNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc fail");return NULL;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}

1.2.3 -> 双向链表销毁

// 双向链表销毁
void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);
}

1.2.4 -> 双向链表打印

// 双向链表打印
void LTPrint(LTNode* phead)
{assert(phead);printf("guard<==>");LTNode* cur = phead->next;while (cur != phead){printf("%d<==>", cur->data);cur = cur->next;}printf("\n");
}

1.2.5 -> 双向链表判空

// 双向链表判空
bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}

1.2.6 -> 双向链表尾插

// 双向链表尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* tail = phead->prev;LTNode* newnode = BuyLTNode(x);tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;// 复用// LTInsert(phead, x);
}
// 尾插测试
void Test1()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTDestory(plist);plist = NULL;
}

 

1.2.7 -> 双向链表尾删

// 双向链表尾删
void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* tail = phead->prev;LTNode* tailPrev = tail->prev;free(tail);tailPrev->next = phead;phead->prev = tailPrev;// 复用// LTErase(phead->prev);
}
// 尾删测试
void Test2()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTDestory(plist);plist = NULL;
}

1.2.8 -> 双向链表头插

// 双向链表头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyLTNode(x);newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;newnode->prev = phead;// 复用// LTInsert(phead->next, x);
}
// 头插测试
void Test3()
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4);LTPushFront(plist, 5);LTPrint(plist);LTDestory(plist);plist = NULL;
}

1.2.9 -> 双向链表头删

// 双向链表头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* first = phead->next;LTNode* second = first->next;phead->next = second;second->prev = phead;free(first);// 复用// LTErase(phead->next);
}
// 头删测试
void Test4()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTDestory(plist);plist = NULL;
}

1.2.10 -> 双向链表查找

// 双向链表查找
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

1.2.11 ->  双向链表在pos的前面进行插入

// 双向链表在pos的前面进行插入
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyLTNode(x);prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}
// 查找插入测试
void Test5()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTNode* pos = LTFind(plist, 3);if (pos)LTInsert(pos, 99);LTPrint(plist);LTDestory(plist);plist = NULL;
}

1.2.12 -> 双向链表删除pos位置的节点

// 双向链表删除pos位置的节点
void LTErase(LTNode* pos)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos);
}

2 -> 顺序表和链表的区别

不同点顺序表链表
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持O(1)不支持:O(N)
任意位置插入或者删除元素可能需要搬移元素,效率低O(N)只需修改指针指向
插入动态顺序表,空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

注:缓存利用率参考存储体系结构以及局部原理性。

3 -> 完整代码

3.1 -> List.c

#include "List.h"// 双向链表初始化
LTNode* LTInit()
{LTNode* phead = BuyLTNode(-1);phead->next = phead;phead->prev = phead;return phead;
}// 动态申请一个结点
LTNode* BuyLTNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc fail");return NULL;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}// 双向链表销毁
void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);
}// 双向链表打印
void LTPrint(LTNode* phead)
{assert(phead);printf("guard<==>");LTNode* cur = phead->next;while (cur != phead){printf("%d<==>", cur->data);cur = cur->next;}printf("\n");
}// 双向链表判空
bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}// 双向链表尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* tail = phead->prev;LTNode* newnode = BuyLTNode(x);tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;// 复用// LTInsert(phead, x);
}// 双向链表尾删
void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* tail = phead->prev;LTNode* tailPrev = tail->prev;free(tail);tailPrev->next = phead;phead->prev = tailPrev;// 复用// LTErase(phead->prev);
}// 双向链表头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyLTNode(x);newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;newnode->prev = phead;// 复用// LTInsert(phead->next, x);
}// 双向链表头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* first = phead->next;LTNode* second = first->next;phead->next = second;second->prev = phead;free(first);// 复用// LTErase(phead->next);
}// 双向链表查找
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}// 双向链表在pos的前面进行插入
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyLTNode(x);prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}// 双向链表删除pos位置的节点
void LTErase(LTNode* pos)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos);
}

3.2 -> List.h

#pragma once#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>// 带头+双向+循环链表增删查改实现
typedef int LTDataType;typedef struct LTNode
{LTDataType data;struct LTNode* next;struct LTNode* prev;
}LTNode;// 双向链表初始化
LTNode* LTInit();// 动态申请一个结点
LTNode* BuyLTNode(LTDataType x);// 双向链表销毁
void LTDestory(LTNode* phead);// 双向链表打印
void LTPrint(LTNode* phead);// 双向链表判空
bool LTEmpty(LTNode* phead);// 双向链表尾插
void LTPushBack(LTNode* phead, LTDataType x);// 双向链表尾删
void LTPopBack(LTNode* phead);// 双向链表头插
void LTPushFront(LTNode* phead, LTDataType x);// 双向链表头删
void LTPopFront(LTNode* phead);// 双向链表查找
LTNode* LTFind(LTNode* phead, LTDataType x);// 双向链表在pos的前面进行插入
void LTInsert(LTNode* pos, LTDataType x);// 双向链表删除pos位置的节点
void LTErase(LTNode* pos);

3.3 -> Test.c

#include "List.h"// 尾插测试
void Test1()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTDestory(plist);plist = NULL;
}// 尾删测试
void Test2()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTDestory(plist);plist = NULL;
}// 头插测试
void Test3()
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4);LTPushFront(plist, 5);LTPrint(plist);LTDestory(plist);plist = NULL;
}// 头删测试
void Test4()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTDestory(plist);plist = NULL;
}// 查找插入测试
void Test5()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTNode* pos = LTFind(plist, 3);if (pos)LTInsert(pos, 99);LTPrint(plist);LTDestory(plist);plist = NULL;
}int main()
{return 0;
}

感谢大佬们支持!!!

互三啦!!!

相关文章:

【海贼王的数据航海:利用数据结构成为数据海洋的霸主】链表—双向链表

目录 往期 1 -> 带头双向循环链表(双链表) 1.1 -> 接口声明 1.2 -> 接口实现 1.2.1 -> 双向链表初始化 1.2.2 -> 动态申请一个结点 1.2.3 -> 双向链表销毁 1.2.4 -> 双向链表打印 1.2.5 -> 双向链表判空 1.2.6 -> 双向链表尾插 1.2.7 -&…...

做测试还是测试开发,选职业要慎重!

【软件测试面试突击班】2024吃透软件测试面试最全八股文攻略教程&#xff0c;一周学完让你面试通过率提高90%&#xff01;&#xff08;自动化测试&#xff09; 突然发现好像挺多人想投测开和测试的&#xff0c;很多人面试的时候也会被问到这几个职位的区别&#xff0c;然后有测…...

Java面试题总结200道(二)

26、简述Spring中Bean的生命周期&#xff1f; 在原生的java环境中&#xff0c;一个新的对象的产生是我们用new()的方式产生出来的。在Spring的IOC容器中&#xff0c;将这一部分的工作帮我们完成了(Bean对象的管理)。既然是对象&#xff0c;就存在生命周期&#xff0c;也就是作用…...

面试数据库篇(mysql)- 03MYSQL支持的存储引擎有哪些, 有什么区别

存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可被称为表类型。 MySQL体系结构 连接层服务层引擎层存储层 存储引擎特点 InnoDB MYSQL支持的存储引擎有哪些, 有什么区别 ? my…...

MySQL深入——25

Join语句如何优化? Join语句的两种算法&#xff0c;分别为Index Nested-Loop Join和Block Nested-Loop Join NLJ在大表Join当中还不错&#xff0c;但BNL在大表join时性能就差很多&#xff0c;很耗CPU资源。 如何优化这两个算法 创建t1&#xff0c;t2算法&#xff0c;在t1中…...

Docker运行时安全之道: 保障容器环境的安全性

引言 Docker作为容器化技术的领军者,为应用部署提供了灵活性和便捷性。然而,在享受这些优势的同时,必须重视Docker运行时的安全性。本文将深入研究一些关键的Docker运行时安全策略,以确保你的容器环境在生产中得到有效的保护。 1. 使用最小特权原则 保持容器以最小权限运…...

前后端分离项目Docker部署指南(上)

目录 前言 一.搭建局域网 1.搭建net-ry局域网&#xff0c;用于部署若依项目 2.注意点 二.安装redis 创建目录 将容器进行挂载 ​编辑 测试是否安装成功 ​编辑 三. 安装MySQL 创建文件夹 上传配置文件并且修改 .启动MySQL容器服务 充许远程连接 四.部署后端 使用…...

ARM 架构下国密算法库

目录 前言GmSSL编译环境准备下载 GmSSL 源码编译 GmSSL 源码SM4 对称加密算法SM2 非对称加密算法小结前言 在当前的国际形式下,国替势不可挡。操作系统上,银河麒麟、统信 UOS、鸿蒙 OS 等国产系统开始发力,而 CPU 市场,也是百花齐放,有 龙芯(LoongArch架构)、兆芯(X86…...

源码的角度分析Vue2数据双向绑定原理

什么是双向绑定 我们先从单向绑定切入&#xff0c;其实单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新。那么双向绑定就可以从此联想到&#xff0c;即在单向绑定的基础上&#xff0c;用户更新…...

动态规划(算法竞赛、蓝桥杯)--树形DP树形背包

1、B站视频链接&#xff1a;E18 树形DP 树形背包_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; const int N110; int n,V,p,root; int v[N],w[N]; int h[N],to[N],ne[N],tot; //邻接表 int f[N][N];void add(int a,int b){to[tot]b;ne[tot]h[a];h[a…...

electron打包前端项目

1.npm run build 打包项目文件到disk文件夹 2.安装electron:npm install electron 打开后进到/dist里面 然后把这个项目的地址配置环境变量 配置环境变量&#xff1a;在系统变量的path中添加进去 配置成功后&#xff0c;electron -v看看版本。 3.创建主程序的入口文件main.…...

2.1基本算法之枚举7647:余数相同问题

已知三个正整数 a&#xff0c;b&#xff0c;c。 现有一个大于1的整数x&#xff0c;将其作为除数分别除a&#xff0c;b&#xff0c;c&#xff0c;得到的余数相同。 请问满足上述条件的x的最小值是多少&#xff1f; 数据保证x有解 #include<bits/stdc.h>//万能头 using…...

求最短路径之迪杰斯特拉算法

对fill用法的介绍 1.用邻接矩阵实现 const int maxn100; const int INF100000000;//无穷大&#xff0c;用来初始化边 int G[maxn][maxn];//用邻接矩阵存储图的信息 int isin[maxn]{false};//记录是否已被访问 int minDis[maxn];//记录到顶点的最小距离void Dijkstra(int s,in…...

python大学社团管理系统开发文档

项目介绍 一直想做一款大学社团管理系统&#xff0c;看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套管理系统。 在线体验 代码下载&#xff1a;https://github.com/geeeeeeeek/python_team演示地址&#xff1a;http://team.gitapp.cn/ &…...

leetcode 1328.破坏回文串

题目链接LeetCode1328 1.题目 给你一个由小写英文字母组成的回文字符串 palindrome &#xff0c;请你将其中 一个 字符用任意小写英文字母替换&#xff0c;使得结果字符串的 字典序最小 &#xff0c;且 不是 回文串。 请你返回结果字符串。如果无法做到&#xff0c;则返回一个…...

重学SpringBoot3-自动配置机制

重学SpringBoot3-自动配置机制 引言Spring Boot 自动配置原理示例&#xff1a;Spring Boot Web 自动配置深入理解总结相关阅读 引言 Spring Boot 的自动配置是其最强大的特性之一&#xff0c;它允许开发者通过最少的配置实现应用程序的快速开发和部署。这一切都得益于 Spring …...

sql基本语法+实验实践

sql语法 注释&#xff1a; 单行 --注释内容# 注释内容多行 /* 注释内容 */数据定义语言DDL 查询所有数据库 show databases;注意是databases而不是database。 查询当前数据库 select database();创建数据库 create database [if not exists] 数据库名 [default charset 字符…...

Node.js中的并发和多线程处理

在Node.js中&#xff0c;处理并发和多线程是一个非常重要的话题。由于Node.js是单线程的&#xff0c;这意味着它在任何给定时间内只能执行一个任务。然而&#xff0c;Node.js的事件驱动和非阻塞I/O模型使得处理并发和多线程变得更加高效和简单。在本文中&#xff0c;我们将探讨…...

node.js 封装分页查询

node.js封装sql分页查询 方法&#xff1a; /*** 生成分页查询sql* param {string} table 表名* param {number} pageNum 分页页数 * param {number} pageSize 分页条数 * param {object} query 查询对象 例&#xff1a;{id:1,name:小明}* returns sql语句*/ const limit (ta…...

iptables 基本使用

iptables 主要用到两个表&#xff1a;filter 和 nat&#xff0c;其中 filter 表可以用来过滤数据包&#xff1b;nat 可以用来修改数据包的源地址和目的地址。 chain chain 是 table 中对数据包进行匹配的规则&#xff0c;对于 filter 来说 chain 有 INPUT & OUTPUT & …...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

JavaScript 标签加载

目录 JavaScript 标签加载script 标签的 async 和 defer 属性&#xff0c;分别代表什么&#xff0c;有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...