手撕单链表(单向,不循环,不带头结点)的基本操作

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk

      ⸝⋆   ━━━┓
     - 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━  ➴ ⷯ

本人座右铭 :   欲达高峰,必忍其痛;欲戴王冠,必承其重。

👑💎💎👑💎💎👑 
💎💎💎自💎💎💎
💎💎💎信💎💎💎
👑💎💎 💎💎👑    希望在看完我的此篇博客后可以对你有帮助哟

👑👑💎💎💎👑👑   此外,希望各位大佬们在看完后,可以互赞互关一下,看到必回
👑👑👑💎👑👑👑

 目录:

前言:对于单链表的基本操作重在考验大家对C语言指针的底子

一:传值传参区别

二:尾插

三:头插

四:尾删

五:头删

六:指定数据的查找

七:指定位置之前的删除

八:指定位置之后的删除

九:任意位置之前的插入

十:任意位置之后的插入

结语


 一:传值传参区别

这里就拿一个比较经典的问题来引入吧!

   写一个函数实现2个数 的交换

 

对于刚刚接触编程的铁子们,对这个结果 可能存在很大的疑惑

不慌不忙,接下来我慢慢给大家解释 

int a = 1, b = 2;
    int* p = &a;
    *p = 3;

想必大家对这个代码应该不会很陌生吧。

此时我们对指针p进行解引用拿到的就是变量 a 

也就是说,此时我们通过借助指针实现了对a   的改变

同理,这里我在调用Swap( )这个函数的时候,是不是进行传地址就可以实现对2个数的交换?

话不多说,接下来我们代码实现

 

 是滴,此时确实实现了2个数的交换

分析:

1)传参的本质:形参是对实参的一份临时拷贝,对形参的临时修改不会影响实参

2)所以说:当需要对变量进行改变的时候,我们就需要传对应的地址就可以

如何理解“ 传对应的地址”

比如说:

      改变int 类型的变量,这时就需要传int*的指针(地址)    

     改变int *类型的变量,这时就需要传int**的指针(地址)    

     改变结构体类型的变量,这时就需要传结构体的指针(地址)

 二:尾插

分析:

1)首先为要插入进来的数据开辟结点

2)链表不为空的时候:注意此时要改变的是结构体

         首先 先找到尾结点( 链表最后一个结点的next为空)

         其次进行尾插

3)链表为空:注意此时改变的是结构体类型的指针(头节点为空)

         直接进行插入即可

草图如下:

对非空的链表插入前:

 插入后:

   接下来可是重头戏,好好看,一不仔细,就错失了,那可就不好理解了,避免这个“瓜”没有吃到,反而懊恼不已

 1)开辟结点为插入的数据:
因为之后插入需要频繁开辟结点,所以这里写成了一个函数
SLNode* BuyNode(DataType x)
{SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));if (newnode == NULL){perror("malloc fail\n");return NULL;}// 对开辟的结点进行初始化newnode->data = x;newnode->next = NULL;return newnode;
}
2)找尾结点:这里就依次遍历即可

注意啦:看看这样写对不???

SLNode* ptail = phead;
    while (ptail)
    {
        ptail = ptail->next;
    }
    ptail->next = newnode;

NO,NO,NO

乍一看,看不出啥问题,这就是“码图”结合了

这里以逻辑结构(人类的思维,为了形象化的理解)来解释

逻辑图:

 

   当ptail这个指针指向3这个结点的时候,是不为空的,所以就继续进入我的循环里,此时的尾结点就变成了NULL这个对应当结点,下面在进行插入自然也是不能把新的结点和我原来链表进行有效的连接起来

找尾结点的正确代码:

 while (ptail->next){ptail = ptail->next;}ptail->next = newnode;

 3)当链表为空的时候我们发现以上代码不可取:

因为此时实参plist  传给我的phead这个形参就是一份临时拷贝,我对phead(结构体指针)改变不影响plist(结构体指针)的变化

有了前面那个传值传参的引入,想必大家此时应该有了见解了吧

没错!

就是实参传结构体指针的地址,形参用二级指针

 对应完整代码:

void SLPushBack(SLNode* *phead, DataType x)
{/*1:开辟结点2:判读是否为空的链表3:非空:找到尾结点;此时改变的是结构体,需要传结构体的地址4:为空:直接插入:  因为改变的是结构体类型的指针,所有需要传结构体类型的指针的地址,涉及到二级指针*/SLNode* newnode = BuyNode(x);if (*phead == NULL)  //为空{newnode->next = *phead;// 对*phead解引用 就是plist这个实参*phead = newnode;return;}//非空/*  找尾结点:errSLNode* ptail = phead;while (ptail){ptail = ptail->next;}ptail->next = newnode;*/SLNode* ptail = *phead;while (ptail->next)  //找尾结点{ptail = ptail->next;}ptail->next = newnode;/*当链表为空的时候,以上代码有问题为空的时候需要对头节点进行改变,注意头节点是结构体类型指针所以需要传地址*/}

 三:头插

分析:

1) 首先为插入数据开辟结点

2)因为此时改变的是结构体指针(plist),所以需要传入结构体指针的地址

void SLPushFront(SLNode** phead, DataType x)
{/*1:为x开辟结点2:更新头节点3:因为改变的是结构体类型的指针,所有需要传结构体类型的指针的地址传参的本质是:拷贝:形参是对实参的一份临时拷贝,对形参的修改不会影响我实参的变化*/SLNode* newnode = BuyNode(x);newnode->next = *phead;// 对*phead解引用 就是plist这个实参*phead = newnode;
}

四:尾删

分析:

1)首先判断链表是否为空;为空不需删除

2)其次:判断链表是否为一个结点;因为此时改变的头节点(结构体指针);那就涉及到了传结构体指针的地址

3)最后就是多个结点的情况:

      先找尾结点

       删除尾结点

 1)先从正常情况说起(多个结点)

 找尾结点:这里需要找到尾结点的前一个结点,避免free(ptail)时找不到新的尾结点

 尾删后:

SLNode* ptail = *phead;SLNode* pre =* phead;while (ptail->next)  //找尾结点{pre = ptail;//保存尾结点的前一个结点ptail = ptail->next;}free(ptail);ptail = pre;//尾结点更新ptail->next = NULL;//不要忘了置空
2)只有一个结点

注意这里需要传入结构体指针的地址

if ((*phead)->next == NULL)  //一个结点,注意*与->优先级{free(*phead);*phead = NULL;return;}
 3)判空

直接暴力检查即可:

assert(*phead);

 对应完整代码:

void SLPopBack(SLNode** phead)
{/*1:判断是否为空2:判断是否为一个结点:因为此时改变的是头节点(结构体指针)3:找到尾结点,此时尾结点的前一个结点成为新的结点4:  *phead 就是头指针  plist*///为空:assert(*phead);if ((*phead)->next == NULL)  //一个结点,注意*与->优先级{free(*phead);*phead = NULL;return;}// 非空SLNode* ptail = *phead;SLNode* pre =* phead;while (ptail->next)  //找尾结点{pre = ptail;//保存尾结点的前一个结点ptail = ptail->next;}free(ptail);ptail = pre;//尾结点更新ptail->next = NULL;//不要忘了置空}

五:头删

相信有了前面的尾删,我们对头删那便是轻轻松拿捏了

1)判空

2)非空

 1)判空

assert(*phead);  //直接暴力检查

2)非空:  删除头节点之前需要保存一下

对应完整代码:

void SLPopFront(SLNode** phead)
{/*1:判是否为空 2:非空:删除头节点之前需要保存一下第二个结点*/assert(*phead);//为空SLNode* psec = (*phead)->next;//保存第二个结点free(*phead);*phead = psec;//更新}
六:指定数据查找

1:若是当前数据存在,则返回对应的结点;否则返回NULL

2:依次遍历

相信有了前面的基础,我们对这个区区查找的代码轻轻松拿下

SLNode* SLFind(SLNode* phead, DataType x)
{/*若是找到返回该节点循环遍历*/SLNode* pcur = phead;while (pcur){if (pcur->data == x)return pcur;//返回节点elsepcur = pcur->next;//更新}return NULL;
}
七:指定位置之前的删除 

分析:

假设对pos这个位置之前的进行删除

1:pos若是为头节点,则不需要删除

2:pos为第二个结点,其实就是进行头删的操作,注意此时改变的是头节点(结构体指针),所以需要传二级指针

3:正常情况:找到pos前一个结点

 1:pos为头节点

直接暴力断言,就像当你作业还没有写完,但你依然再玩游戏此时你的父亲突然过来问你,作业写完了吗,你回答到:没有。你父亲直接就是一顿说,此时你就乖乖去写作业了

assert(*phead != pos);

2:pos 为第二个结点

if ((*phead)->next == pos)//pos为第二个结点
    {
        free(*phead);
        *phead = pos;//pos是新的头节点
    }

3:正常情况
SLNode* pre = *phead;while (pre->next->next != pos){pre = pre->next;}free(pre->next);pre->next = pos;

对应完整代码: 

void SLEarseBefore(SLNode** phead, SLNode* pos)
{/*1:pos为头节点是不可以删除的2:pos为第二个结点,此时要删除的是头节点,改变的是结构体指针(phead),需要二级指针3:正常情况,找到pos前一个结点*/assert(pos != *phead);//保证pos不为头节点if ((*phead)->next == pos)//pos为第二个结点{free(*phead);*phead = pos;//pos是新的头节点}else{SLNode* pre = *phead;while (pre->next->next != pos){pre = pre->next;}free(pre->next);pre->next = pos;}
}
八:指定位置之后的删除

分析:假设要删除的位置是pos

    1:pos为最后一个结点;没有必要删除
    2:pos不为最后一个结点

对应代码:

void SLEarseAfter(SLNode** phead, SLNode* pos)
{/*1:pos为最后一个结点;没有必要删除2:pos不为最后一个结点*/assert(pos->next != NULL);//暴力判断是否为最后一个SLNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}
九:任意位置之前的插入

假设任意位置为pos

1:pos为头节点:可以借助头插的函数进行,注意此时改变的是头节点(结构体指针),要传结构体指针的地址

2:pos不是头节点:需要找到pos的前一个结点

3:为要插入的数据开辟结点

 对应代码:

void SLInsertBefore(SLNode** phead, SLNode* pos, DataType x)
{/**1:开辟结点2:找到pos前面的结点(pos不是头节点)3:pos是头节点此时变成头插*/SLNode* newnode = BuyNode(x);if (pos == *phead){SLPushFront(phead, x);return;}else{SLNode* pre = *phead;while (pre->next != pos){pre = pre->next;}//插入pre->next = newnode;newnode->next = pos;}
}
十:任意位置之后的插入

分析:假设此位置是pos

1:开辟结点

2:保存pos后面的那个结点SLNode* p =  pos->next

3: 直接插入

void SLInsertAfter(SLNode* phead, SLNode* pos, DataType x)
{/*1:开辟结点2:保存一下pos后面的那结点(否则会连不上)3:直接插入*/SLNode* newnode = BuyNode(x);SLNode* p = pos->next;//保存pos后的结点//插入pos->next = newnode;newnode->next = p;
}

 整个单链表完整代码:

SList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;
typedef struct SListNode
{DataType data;//数据域struct SListNode* next;//指针域
}SLNode;void SLPrint(SLNode* phead);
void SLPushFront(SLNode** phead, DataType x);
void SLPushBack(SLNode** phead, DataType x);
void SLPopBack(SLNode** phead);
void SLPopFront(SLNode** phead); 
SLNode* SLFind(SLNode* phead, DataType x);//对指定数据进行查找
void SLModify(SLNode* phead, SLNode*pos,DataType x);void SLInsertBefore(SLNode** phead, SLNode* pos, DataType x);//在指定数据之前插入
void SLInsertAfter(SLNode* phead, SLNode* pos, DataType x);//在指定数据之前插入void SLEarseBefore(SLNode** phead, SLNode* pos);//任意位置之前的删除
void SLEarseAfter(SLNode** phead, SLNode* pos);//任意位置之后的删除
SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"void SLPrint(SLNode* phead)
{SLNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;//更新}printf("NULL\n");
}
SLNode* BuyNode(DataType x)
{SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));if (newnode == NULL){perror("malloc fail\n");return NULL;}// 对开辟的结点进行初始化newnode->data = x;newnode->next = NULL;return newnode;
}
void SLPushFront(SLNode** phead, DataType x)
{/*1:为x开辟结点2:更新头节点3:因为改变的是结构体类型的指针,所有需要传结构体类型的指针的地址传参的本质是:拷贝:形参是对实参的一份临时拷贝,对形参的修改不会影响我实参的变化*/SLNode* newnode = BuyNode(x);newnode->next = *phead;// 对*phead解引用 就是plist这个实参*phead = newnode;
}
void SLPushBack(SLNode* *phead, DataType x)
{/*1:开辟结点2:判读是否为空的链表3:非空:找到尾结点;此时改变的是结构体,需要传结构体的地址4:为空:直接插入:  因为改变的是结构体类型的指针,所有需要传结构体类型的指针的地址,涉及到二级指针*/SLNode* newnode = BuyNode(x);if (*phead == NULL)  //为空{newnode->next = *phead;// 对*phead解引用 就是plist这个实参*phead = newnode;return;}//非空/*  找尾结点:errSLNode* ptail = phead;while (ptail){ptail = ptail->next;}ptail->next = newnode;*/SLNode* ptail = *phead;while (ptail->next)  //找尾结点{ptail = ptail->next;}ptail->next = newnode;/*当链表为空的时候,以上代码有问题为空的时候需要对头节点进行改变,注意头节点是结构体类型指针所以需要传地址*/}
void SLPopBack(SLNode** phead)
{/*1:判断是否为空2:判断是否为一个结点:因为此时改变的是头节点(结构体指针)3:找到尾结点,此时尾结点的前一个结点成为新的结点4:  *phead 就是头指针  plist*///为空:assert(*phead);if ((*phead)->next == NULL)  //一个结点,注意*与->优先级{free(*phead);*phead = NULL;return;}// 非空SLNode* ptail = *phead;SLNode* pre =* phead;while (ptail->next)  //找尾结点{pre = ptail;//保存尾结点的前一个结点ptail = ptail->next;}free(ptail);ptail = pre;//尾结点更新ptail->next = NULL;//不用忘了置空//对一个与多个节点的操作可以合并//只要找到倒数第二个结点就可以/*SLNode* ptail = *phead;while (ptail->next->next){ptail = ptail->next;}free(ptail->next);ptail->next = NULL;*/}
void SLPopFront(SLNode** phead)
{/*1:判是否为空 2:非空:删除头节点之前需要保存一下第二个结点*/assert(*phead);//为空SLNode* psec = (*phead)->next;//保存第二个结点free(*phead);*phead = psec;//更新
}
SLNode* SLFind(SLNode* phead, DataType x)
{/*若是找到返回该节点循环遍历*/SLNode* pcur = phead;while (pcur){if (pcur->data == x)return pcur;//返回节点elsepcur = pcur->next;//更新}return NULL;
}
void SLInsertBefore(SLNode** phead, SLNode* pos, DataType x)
{/**1:开辟结点2:找到pos前面的结点(pos不是头节点)3:pos是头节点此时变成头插*/SLNode* newnode = BuyNode(x);if (pos == *phead){SLPushFront(phead, x);return;}else{SLNode* pre = *phead;while (pre->next != pos){pre = pre->next;}//插入pre->next = newnode;newnode->next = pos;}
}
void SLInsertAfter(SLNode* phead, SLNode* pos, DataType x)
{/*1:开辟结点2:保存一下pos后面的那结点(否则会连不上)3:直接插入*/SLNode* newnode = BuyNode(x);SLNode* p = pos->next;//保存pos后的结点//插入pos->next = newnode;newnode->next = p;
}
void SLEarseBefore(SLNode** phead, SLNode* pos)
{/*1:pos为头节点是不可以删除的2:pos为第二个结点,此时要删除的是头节点,改变的是结构体指针(phead),需要二级指针3:正常情况,找到pos前一个结点*/assert(pos != *phead);//保证pos不为头节点if ((*phead)->next == pos)//pos为第二个结点{free(*phead);*phead = pos;//pos是新的头节点}else{SLNode* pre = *phead;while (pre->next->next != pos){pre = pre->next;}free(pre->next);pre->next = pos;SLNode* pre = *phead;while (pre->next->next != pos){pre = pre->next;}free(pre->next);pre->next = pos;}
}
void SLEarseAfter(SLNode** phead, SLNode* pos)
{/*1:pos为最后一个结点;没有必要删除2:pos不为最后一个结点*/assert(pos->next != NULL);//暴力判断是否为最后一个SLNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}
void SLModify(SLNode* phead, SLNode* pos, DataType x)
{assert(phead);pos->data = x;}
test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"void TestPush()
{SLNode* plist = NULL;//SLPushFront(&plist,1);//SLPushFront(&plist,2);//SLPushFront(&plist,3);//SLPrint(plist);SLPushBack(&plist, 4);SLPushBack(&plist, 5);SLPrint(plist);}
void TestPop()
{SLNode* plist = NULL;SLPushBack(&plist, 4);SLPushBack(&plist, 5);SLPushBack(&plist, 6);SLPushBack(&plist, 7);SLPrint(plist);SLNode* pos = SLFind(plist, 7);if(pos)//避免pos为空SLInsertAfter(plist, pos, 44);SLPrint(plist);/*SLPopBack(&plist);SLPrint(plist);SLPopBack(&plist);*//*SLPopFront(&plist);SLPrint(plist);SLPopFront(&plist);SLPrint(plist);*/}
void TestEarse()
{SLNode* plist = NULL;SLPushBack(&plist, 4);SLPushBack(&plist, 5);SLPushBack(&plist, 6);SLPushBack(&plist, 7);SLPrint(plist);SLNode* pos = SLFind(plist, 7);if (pos)//避免pos为空//SLEarseAfter(&plist, pos);SLModify(plist, pos, 77);SLPrint(plist);
}void Swap(int *x, int* y)
{int tmp = *x;//中间变量*x = *y;*y = tmp;
}
int main()
{TestEarse();return 0;/*总结:1:是指针不一定必须断言,是否断言取决于你的操作2:在函数外面改变变量,需要传地址,想改变谁,就传对应类型的地址3:对于链表这块一定注意自己要改变的是结构体还是结构体指针???因为这决定了传的地址类型不一样4:找*/
}

结语:

对于初学单链表的小白来讲(比如我本人,哈哈哈),这个理解起来确实不是那么顺手,其实重点在指针和结构体的掌握。当然自己也需要反复的体会其中的奥妙,

都看到这里了,屏幕前的你,咱一波关注走起呗,你的支持是我不懈的动力,蟹蟹

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

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

相关文章

mercury靶机

文章妙语 不与伪君子争名&#xff0c;不与真小人争利&#xff0c;不与执拗人争理&#xff0c;不与匹夫争勇&#xff0c;不与酸儒争才。不与蠢人施恩 一、信息收集 主机探测 端口探测 探测主机详细版本信息 8080开了http服务 目录扫描 robots.txt目录下什么也没有 二&#xff0…

Python | Iter/genartor | 一文了解迭代器、生成器的含义\区别\优缺点

前提 一种技术的出现&#xff0c;需要考虑&#xff1a; 为了实现什么样的需求&#xff1b;遇到了什么样的问题&#xff1b;采用了什么样的方案&#xff1b;最终接近或达到了预期的效果。 概念 提前理解几个概念&#xff1a; 迭代 我们经常听到产品迭代、技术迭代、功能迭代…

零基础学习数学建模——(二)数学建模的步骤

本篇博客将详细介绍数学建模的步骤。 文章目录 引例&#xff1a;年夜饭的准备第一步&#xff1a;模型准备第二步&#xff1a;模型假设第三步&#xff1a;模型建立第四步&#xff1a;模型求解第五步&#xff1a;结果分析第六步&#xff1a;模型检验第七步&#xff1a;模型应用及…

openeuler的安装和两台linux主机配置ssh实现互相免密登陆

一、openeuler的安装 下载OpenEuler - 网址&#xff1a;https://www.openeuler.org/zh/download/archive/ - 版本选择&#xff1a;openEuler 22.03 LTS SP2 &#xff08;镜像文件&#xff09; &#xff0c;即长期更新版 设置自定义硬件 内存&#xff1a;推荐2GB 处理器&…

oracle基本用户管理和权限分配

1.用户与模式的关系&#xff0c;一一对应的关系 2.创建与管理用户 2.1创建用户语法 CREATE user wdf IDENTIFIED by tiger--创建用户wdf,密码tiger DEFAULT tablespace users--用户的默认表空间 quota 10M on users;--在表空间的占用最大空间 注意&#xff1a;用户创建以后…

rke2 Offline Deploy Rancher v2.8.0 latest (helm 离线部署 rancher v2.8.0)

文章目录 预备条件为什么是三个节点&#xff1f;​预备条件配置私有仓库介质清单安装 helm安装 cert-manager下载介质镜像入库helm 部署卸载 安装 rancher镜像入库helm 安装 验证 预备条件 所有支持的操作系统都使用 64-bit x86 架构。Rancher 兼容当前所有的主流 Linux 发行版…

如何通过兴趣爱好选职业?

一个错误的选择&#xff0c;可能造成终身的遗憾&#xff0c;一个正确的选择&#xff0c;可以让我们少奋斗几十年。所以无论现在付出多少代价&#xff0c;多花一些时间&#xff0c;去研究以下未来的职业方向&#xff0c;这是值得的。 职业定位&#xff08;专业定位&#xff09;…

深兰科技AI医疗健康产品获3000台采购订单

12月6日&#xff0c;武汉某企业与深兰科技签署协议&#xff0c;一次性采购3000台深兰科技AI生理健康检测仪——扁鹊。 深兰科技AI生理健康检测仪——扁鹊是深兰科技推出的人体生理指标检测产品。基于AI生物技术、融合互联网医疗及AIoT技术&#xff0c;深兰科技AI生理健康检测仪…

YOLOv8-Seg改进:轻量化改进 | 华为Ghostnet,超越谷歌MobileNet | CVPR2020

🚀🚀🚀本文改进: Ghost bottleneck为堆叠Ghost模块 ,与YOLOV8建立轻量C2f_GhostBottleneck 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提…

HubSpot CRM:卓越客户服务的关键引擎

在数字化时代&#xff0c;提供卓越的客户服务是企业成功的关键之一。HubSpot CRM以其强大的功能和灵活性&#xff0c;成为实现卓越客户服务的关键引擎&#xff0c;以下是强调HubSpot CRM在客户服务中的应用的关键方面&#xff1a; 1. 全面的客户视图 HubSpot CRM集成了全面的…

《路由与交换技术》---练习题(无答案纯享版)

注意&#xff01;&#xff01;&#xff01;这篇blog是无答案纯享版的 选择填空的答案我会放评论区 简答题可以看这里 计算题可以发私信问我&#xff08;当然WeChat也成&#xff09;but回讯息很慢 一、选择题 1.以下不会在路由表里出现的是: ( ) A.下一跳地址 B.网络地址 C…

科大讯飞星火大模型加持数字员工系列产品发布

面对时代浪潮&#xff0c;基业长青的企业总会率先拥抱变化&#xff0c;在时代交替中创造新的增长空间。当数字化浪潮涌入千行百业&#xff0c;企业掌舵者如何选择转型&#xff1f; 从数字员工到灯塔工厂&#xff0c;愈发成熟的人工智能技术已深入企业管理&#xff0c;持续提高…

小白苦恼:电脑那么多USB口,怎么知道哪个读写更快?

前言 最近有个朋友和小白抱怨&#xff1a;电脑那么多USB接口&#xff0c;有些接口在传输文件的时候实在慢的很。 电脑诞生以来&#xff0c;USB接口就一直存在。但是USB接口还是长得几乎一样&#xff0c;不仔细去研究都不知道哪个USB会更快。 许多小伙伴就会直接放弃辨认&…

计算机导论03-计算机组成

计算机系统结构 冯•诺依曼体系结构 冯•诺依曼体系结构的基本要点 冯•诺依曼思想即冯•诺依曼体系结构思想&#xff0c;其最基本的概念是存储程序概念&#xff0c;它奠定了现代计算机的结构基础。 功能部件: 计算机必须具备五大基本组成部件&#xff0c;包括&#xff1a;运…

程序员试用期转正工作总结

一、试用期工作总结 在公司的三个月试用期中&#xff0c;我完成了以下工作&#xff1a; 完成了XX个功能模块的开发&#xff0c;包括XX模块、XX模块和XX模块。参与了XX个项目的开发和上线&#xff0c;其中XX项目、XX项目和XX项目是我主导的。优化了现有系统的性能&#xff0c;特…

Anaconda定制Python编程并打包

本文主要介绍如何使用Anaconda定制一个Python编程环境并打包&#xff0c;方便编程环境迁移。 文章参考 谢作如 邱奕盛两位老师的《为信息科技教学定制一个Python编程环境》 * 开发不同的项目需要不同的库&#xff08;甚至不同版本&#xff09;&#xff0c;把所有的库安装到一…

mac录屏软件有哪些?分享5个实用软件

mac录屏软件有哪些&#xff1f;随着Mac电脑在创意和专业领域的使用日益普及&#xff0c;越来越多的用户需要录制屏幕内容以进行分享、演示或后期编辑。本文将为您介绍几款知名的Mac录屏软件&#xff0c;让您轻松实现屏幕录制的需求。 1.迅捷屏幕录像工具 这是一款功能强大的屏…

掌握Java Future模式及其灵活应用

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;今天咱们来聊聊Future。咱们程序员在日常工作中&#xff0c;肯定都遇到过需要处理耗时任务的情况&#xff0c;特别是在Java领域。比如说&#xff0c;小黑要从网络上下载数据&#xff0c;或者要执行一个计算密集型…

推理证明-条件等价式、德摩根律、双条件

对于命题逻辑部分来说&#xff0c;只需要掌握命题的符号化&#xff0c;以及如何进行推理证明即可。足矣。其他的都是一些基本的概念&#xff0c;扫一遍&#xff0c;记住即可。 对于什么是命题&#xff1a;陈述句、能判断、真值唯一 进行推理证明&#xff0c;我们需要记住以下…

渐进增强与优雅降级:提升用户体验的双重策略

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…