一文教会你单向链表

目录

一、什么是链表?

1.链表的定义

2.链表的实现

2.1链表的定义

2.2创建一个链表

 二、链表的各个接口

1.创建节点

2.头插(将新创建的节点作为头插入到链表中)

3.打印链表

 4.尾插(将新创建的节点插入到链表的末端)

5.头删

 6.尾删

7.查找

8.删除指定节点位置之后

 9.删除指定位置节点

 10.在指定位置节点之后插入

 11.在指定位置节点之前插入

三、全部代码

1.接口头文件

2.接口实现

3.测试


一、什么是链表?

1.链表的定义

链表是是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。比较通俗易懂的说法就是,在计算机内存中开辟了一个个空间,然后通过地址的方式将它们链接在一起,并通过地址的方式进行访问。

2.链表的实现

只知道了链表的定义,估计大家还是云里雾里的,不知道什么才算是链表,接下来笔者就手动创建一个很挫的链表给大家,不通过函数的形式实现,主要是让大家先感受一下。

2.1链表的定义

在手动创建链表之前,我们要先对链表进行定义,对链表的定义,接口函数的引用和头文件的引用最好放在一个头文件中   这样在要使用创建的接口时便只需要引用一个头文件即可,而接口函数的实现你也可以放在一个.c文件中,最后在另一个.c文件中引用函数测试即可,如图: 

//链表博客版.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
//链表成员我们先用int,int简单好懂
//而之所以要给它取个SLDateType的别名
//不仅仅是因为方便和int进行区分
//更主要的是以后链表的成员不想用int类型的话
//直接在这里进行修改即可
typedef struct SlistNode
{SLDateType data;//成员struct SlistNode* next;//这里给它取名叫next其实是为了方便到时使用,其实你叫它abc也是可以的// 在链表中,一个节点通过地址链接到下一个节点,就像串串一样把它们穿起来,而这个地址则是它们唯一的联系,//我们这讲述的是单向链表,所以只能够是前面的找到后面的,从后面找到前面是不可能实现的。
}SlistNode;

2.2创建一个链表

链表,其实也没什么高大上的,就是通过地址找到下一个节点然后进行对应的访问,核心在于地址上   只要我们能够将首节点的地址链接到下一个节点,将下一个节点的地址链接到下下个节点的地址.....直到链接完成就停止即可,这里我们就先不链接那么多个节点,我们就简单的链接个节点数为3的链表

#include"链表博客版.h"
int main()
{SlistNode a, b, c;//创建三个节点a.next=&b;//a节点的链接部分存储b节点的地址b.next = &c;//b节点的链接部分存储c节点的地址c.next = NULL;//最后一个链接到空指针上,代表着链接结束a.data = 1;b.data = 2;c.data = 3;SlistNode* plist = &a;//将首节点保存while (plist){printf("%d ", plist->data);//打印节点内的内容plist = plist->next;//不断地指向下一个节点,直到为空}
}

 二、链表的各个接口

1.创建节点

创建节点是一个很重要的函数,在插入函数中需要使用。在函数中创建节点,我们就不能够像之前一样直接创建了,众所周知,在函数上创建节点出了函数就会自动销毁,为了避免节点被自动销毁,这里采用malloc的方式创建节点,别忘了在头文件中引用函数

#include"链表博客版.h"
SlistNode* buy_slistnode(SLDateType x)
//使用节点指针作为返回类型,来拿到创建好的新节点
{SlistNode* newnode = (SlistNode*)malloc(sizeof(SlistNode));//使用malloc创建一个新节点if (newnode == NULL){perror("buy_slistnode");exit(-1);//创建失败直接中止程序}newnode->data = x;//将节点内容修改成需要的值newnode->next = NULL;//将链接对象置为空,因为不知道要链接谁return newnode;
}

2.头插(将新创建的节点作为头插入到链表中)

为什么先将头插节点呢?无他,相比尾插它简单很多

void slist_pushfront(SlistNode** phead, SLDateType x)
//采用二级指针的原因是,当没有节点的时候,我们要对首节点的地址进行修改
{//先创建一个新的节点SlistNode* newnode = buy_slistnode(x);//我们要头插是吧,也就是说新创建的节点是新的头//那么我们是不是应该把我们自己原来的头更新一下//然后再将之前的节点,也就是之前的头链接到新的头后面/*	*phead = newnode;newnode->next = *phead;*///但这是错误的,原因很简单,你的头更新了,那么你就找不到之前的节点了//换一下顺序即可newnode->next = *phead;*phead = newnode;
}

3.打印链表

插入完节点之后,也不知道自己到底有没有插入,因此我们来设计一个打印链表的函数

void print_slist(SlistNode* phead)
{while (phead)//phead不为空意味着还有节点没被访问完{printf("%d->", phead->data);phead=phead->next;//指向下一个节点}printf("NULL\n");//访问完了打印空,提示已经访问完了
}

测试效果:

#include"链表博客版.h"
void test1()
{SlistNode* plist = NULL;//创建一个链表头slist_pushfront(&plist, 1);//依次将1,2,3头插进链表中slist_pushfront(&plist, 2);//那么链表最后应该是3为头,1为尾slist_pushfront(&plist, 3);print_slist(plist);
}
int main()
{test1();
}

 4.尾插(将新创建的节点插入到链表的末端)

尾插要在链表的末端进行插入,那么找到链表的末端是一件必须要做的事

void slist_pushback(SlistNode** phead, SLDateType x)
{SlistNode* tmp = *phead;//创建一个首节点的拷贝,避免影响到首节点的指向SlistNode* newnode = buy_slistnode(x);//创建一个新节点while(tmp->next)//当成员的next为空的时候意味着已经找到目标了// 跳出循环//接下来就是把这个成员的指向改变{tmp = tmp->next;}tmp->next = newnode;
}

很多小伙伴,写到这里的时候就以为已经完成了,但你想一想,如果此时链表中没有节点呢,也就是*phead此时为NULL的时候,你还能够指向next吗,你能对空指针进行解引用吗?显然不能,因此我们把这种情况单独处理。

void slist_pushback(SlistNode** phead, SLDateType x)
{SlistNode* tmp = *phead;//创建一个首节点的拷贝,避免影响到首节点的指向SlistNode* newnode = buy_slistnode(x);//创建一个新节点if (*phead==NULL)//当*phead==NULL时,意味着链表为空{*phead = newnode;//直接链接return;}while(tmp->next)//当成员的next为空的时候意味着已经找到目标了// 跳出循环//接下来就是把这个成员的指向改变{tmp = tmp->next;}tmp->next = newnode;
}

测试代码:

void test2()
{SlistNode* plist = NULL;slist_pushback(&plist, 10086);//依次尾插10086,666,555,111slist_pushback(&plist, 666);slist_pushback(&plist, 555);slist_pushback(&plist, 111);print_slist(plist);
}
int main()
{test2();
}

错误情况

程序直接就崩溃了,连print_slist即使是空也应该打印出来的NULL都没打印出来

正确情况

5.头删

void slist_popfront(SlistNode** phead)
{if (*phead==NULL)//空了就别删了{printf("链表为空,操作失败\n");return;}SlistNode* tmp = (*phead)->next;//储存头的下一个节点,避免找不到free(*phead);//直接释放头节点*phead =tmp;//头节点重新指向下一个节点
}

 效果测试:

void test3()
{SlistNode* plist = NULL;slist_popfront(&plist);//直接删除,测试报错slist_pushback(&plist, 10086);//依次尾插10086,666,555,111slist_pushback(&plist, 666);slist_pushback(&plist, 555);slist_pushback(&plist, 111);print_slist(plist);slist_popfront(&plist);//删除10086print_slist(plist);slist_popfront(&plist);//删除666print_slist(plist);slist_popfront(&plist);//删除555print_slist(plist);slist_popfront(&plist);//删除111print_slist(plist);
}int main()
{test3();
}

 6.尾删

void slist_popback(SlistNode** phead)
{if (*phead == NULL){printf("链表为空,操作失败\n");return;}if ((*phead)->next == NULL)//如果只有一个节点,我们就不可能找到上一个节点,因此单独处理{free(*phead);//直接释放*phead = NULL;return;}SlistNode* tmp = *phead;SlistNode* prev = NULL;//用来存储目标的上一个节点while (tmp->next){prev = tmp;tmp=tmp->next;}prev->next = NULL;//改变上一个节点的指向free(tmp);
}

测试代码:

void test4()
{SlistNode* plist = NULL;slist_popback(&plist);//直接删除,测试报错slist_pushback(&plist, 10086);//依次尾插10086,666,555,111slist_pushback(&plist, 666);slist_pushback(&plist, 555);slist_pushback(&plist, 111);print_slist(plist);slist_popback(&plist);//删除111print_slist(plist);slist_popback(&plist);//删除555print_slist(plist);slist_popback(&plist);//删除666print_slist(plist);slist_popback(&plist);//删除10086print_slist(plist);slist_popback(&plist);//删除空链表print_slist(plist);
}int main()
{test4();
}

7.查找

在对指定位置操作之前,我们得先找到目标位置才行,找到目标位置是比较简单的,简单地遍历一遍链表,找的到就返回对应的地址,找不到就返回空指针

SlistNode* slist_find(SlistNode* phead,SLDateType x)
{while (phead){if (phead->data == x){return phead;}phead=phead->next;}return NULL;
}

8.删除指定节点位置之后

之所以先讲指定位置之后删除,是因为这个相比指定位置删除简单很多

void slist_erase_after(SlistNode* pos)
{if (pos == NULL ||pos->next==NULL )//如果为空则删除失败,如果下一个节点为空也不能删除{printf("该位置无效,操作失败\n");return;}SlistNode* tmp = pos->next;pos->next = pos->next->next;free(tmp);
}

测试代码

void test5()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中slist_pushback(&plist, 2);slist_pushback(&plist, 3);print_slist(plist); SlistNode* pos=slist_find(plist,1);//查找1所在的位置slist_erase_after(pos);//将1之后删除print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_erase_after(pos);//将3之后删除,但是3之后没有节点,删除必定失败print_slist(plist);
}
int main()
{test5();
}

 9.删除指定位置节点

void slist_erase(SlistNode* pos,SlistNode**phead)
{if (pos == NULL)//为空就别删了{printf("该位置无效,操作失败\n");return;}if(*phead==pos)//当只有一个节点时,操作不到两个节点,单独处理{SlistNode*tmp=(*phead)->next;free(*phead);*phead = tmp;return;}SlistNode* cur = *phead;while (cur->next){if (cur->next == pos){break;}cur=cur->next;}//此时phead的next就是目标节点SlistNode* tmp = cur->next;cur->next = cur->next->next;//将目标节点的上一个节点链接到目标节点的下一个地址free(tmp);
}

测试代码:

void test6()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中slist_pushback(&plist, 2);slist_pushback(&plist, 3);print_slist(plist);SlistNode* pos = slist_find(plist, 1);//查找1所在的位置slist_erase(pos, &plist);//将1删除print_slist(plist);	pos = slist_find(plist, 2);//查找2所在的位置slist_erase(pos, &plist);//将2删除print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_erase(pos, &plist);//将3删除print_slist(plist);
}
int main()
{test6();
}

 10.在指定位置节点之后插入

void slist_insert_after(SlistNode* pos, SLDateType x)
{if (pos == NULL){printf("目标不存在,操作失败\n");return;}SlistNode* newnode = buy_slistnode(x);newnode->next = pos->next;pos->next = newnode;
}

测试代码:

void test7()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中slist_pushback(&plist, 2);slist_pushback(&plist, 3);SlistNode* pos = slist_find(plist, 1);//查找1所在的位置slist_insert_after(pos, 10086);//在1之后进行插入print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_insert_after(pos, 520);//在3之后进行插入print_slist(plist);pos = slist_find(plist, 10086);//查找10086所在的位置slist_insert_after(pos,9 );//在10086之后进行插入print_slist(plist);
}
int main()
{test7();
}

 11.在指定位置节点之前插入

void slist_insert_before(SlistNode* pos, SLDateType x,SlistNode**phead)
{if (pos == NULL){printf("目标不存在,操作失败\n");return;}	SlistNode* newnode = buy_slistnode(x);if (*phead==pos)//在第一个节点前插入,没有上一个节点,单独处理{newnode->next = pos;*phead = newnode;return;}SlistNode* cur = *phead;while (cur)//为空意味着找不到{if (cur->next == pos)//找到上一个节点了{break;}cur = cur->next;}if (cur == NULL){printf("目标不存在,操作失败\n");return;}cur->next = newnode;newnode->next = pos;
}

测试代码

void test8()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中print_slist(plist);SlistNode* pos = slist_find(plist, 1);//查找1所在的位置slist_insert_before(pos, 10086,&plist);//在1之前插入666print_slist(plist);slist_pushback(&plist, 2);slist_pushback(&plist, 3);pos = slist_find(plist, 10086);//查找10086所在的位置slist_insert_before(pos, 666, &plist);//在10086之前插入666print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_insert_before(pos, 999, &plist);//在3之前插入999print_slist(plist);}
int main()
{test8();
}

三、全部代码

1.接口头文件

//链表博客版.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
//链表成员我们先用int,int简单好懂
//而之所以要给它取个SLDateType的别名
//不仅仅是因为方便和int进行区分
//更主要的是以后链表的成员不想用int类型的话
//直接在这里进行修改即可
typedef struct SlistNode
{SLDateType data;//成员struct SlistNode* next;//这里给它取名叫next其实是为了方便到时使用,其实你叫它abc也是可以的// 在链表中,一个节点通过地址链接到下一个节点,就像串串一样把它们穿起来,而这个地址则是它们唯一的联系,//我们这讲述的是单向链表,所以只能够是前面的找到后面的,从后面找到前面是不可能实现的。
}SlistNode;
SlistNode* buy_slistnode(SLDateType x);
//头插
void slist_pushfront(SlistNode**phead,SLDateType x);
//打印链表
void print_slist(SlistNode* phead);
//尾插
void slist_pushback(SlistNode** phead, SLDateType x);
//头删
void slist_popfront(SlistNode** phead);
//尾删
void slist_popback(SlistNode**phead);
//查找
SlistNode* slist_find(SlistNode*phead,SLDateType x);
//删除指定位置之后
void slist_erase_after(SlistNode*pos);
//删除指定位置
void slist_erase(SlistNode* pos,SlistNode**phead);
//在指定位置之后插入
void slist_insert_after(SlistNode* pos, SLDateType x);
//在指定位置之前插入
void slist_insert_before(SlistNode* pos, SLDateType x, SlistNode** phead);

2.接口实现

#include"链表博客版.h"
SlistNode* buy_slistnode(SLDateType x)
//使用节点指针作为返回类型,来拿到创建好的新节点
{SlistNode* newnode = (SlistNode*)malloc(sizeof(SlistNode));//使用malloc创建一个新节点if (newnode == NULL){perror("buy_slistnode");exit(-1);//创建失败直接中止程序}newnode->data = x;//将节点内容修改成需要的值newnode->next = NULL;//将链接对象置为空,因为不知道要链接谁return newnode;
}
void slist_pushfront(SlistNode** phead, SLDateType x)
//采用二级指针的原因是,当没有节点的时候,我们要对首节点的地址进行修改
{//先创建一个新的节点SlistNode* newnode = buy_slistnode(x);//我们要头插是吧,也就是说新创建的节点是新的头//那么我们是不是应该把我们自己原来的头更新一下//然后再将之前的节点,也就是之前的头链接到新的头后面/*	*phead = newnode;newnode->next = *phead;*///但这是错误的,原因很简单,你的头更新了,那么你就找不到之前的节点了//换一下顺序即可newnode->next = *phead;*phead = newnode;
}
void print_slist(SlistNode* phead)
{while (phead)//phead不为空意味着还有节点没被访问完{printf("%d->", phead->data);phead=phead->next;//指向下一个节点}printf("NULL\n");//访问完了打印空,提示已经访问完了
}
void slist_pushback(SlistNode** phead, SLDateType x)
{SlistNode* tmp = *phead;//创建一个首节点的拷贝,避免影响到首节点的指向SlistNode* newnode = buy_slistnode(x);//创建一个新节点if (*phead==NULL)//当*phead==NULL时,意味着链表为空{*phead = newnode;//直接链接return;}while(tmp->next)//当成员的next为空的时候意味着已经找到目标了// 跳出循环//接下来就是把这个成员的指向改变{tmp = tmp->next;}tmp->next = newnode;
}
void slist_popfront(SlistNode** phead)
{if (*phead==NULL)//空了就别删了{printf("链表为空,操作失败\n");return;}SlistNode* tmp = (*phead)->next;//储存头的下一个节点,避免找不到free(*phead);//直接释放头节点*phead =tmp;//头节点重新指向下一个节点
}
void slist_popback(SlistNode** phead)
{if (*phead == NULL){printf("链表为空,操作失败\n");return;}if ((*phead)->next == NULL)//如果只有一个节点,我们就不可能找到上一个节点,因此单独处理{free(*phead);//直接释放*phead = NULL;return;}SlistNode* tmp = *phead;SlistNode* prev = NULL;//用来存储目标的上一个节点while (tmp->next){prev = tmp;tmp=tmp->next;}prev->next = NULL;//改变上一个节点的指向free(tmp);
}
SlistNode* slist_find(SlistNode* phead,SLDateType x)
{while (phead){if (phead->data == x){return phead;}phead=phead->next;}return NULL;
}
void slist_erase_after(SlistNode* pos)
{if (pos == NULL ||pos->next==NULL )//如果为空则删除失败,如果下一个节点为空也不能删除{printf("该位置无效,操作失败\n");return;}SlistNode* tmp = pos->next;pos->next = pos->next->next;free(tmp);
}
void slist_erase(SlistNode* pos,SlistNode**phead)
{if (pos == NULL)//为空就别删了{printf("该位置无效,操作失败\n");return;}if(*phead==pos)//当只有一个节点时,操作不到两个节点,单独处理{SlistNode*tmp=(*phead)->next;free(*phead);*phead = tmp;return;}SlistNode* cur = *phead;while (cur->next){if (cur->next == pos){break;}cur=cur->next;}//此时phead的next就是目标节点SlistNode* tmp = cur->next;cur->next = cur->next->next;//将目标节点的上一个节点链接到目标节点的下一个地址free(tmp);
}
void slist_insert_after(SlistNode* pos, SLDateType x)
{if (pos == NULL){printf("目标不存在,操作失败\n");return;}SlistNode* newnode = buy_slistnode(x);newnode->next = pos->next;pos->next = newnode;
}
void slist_insert_before(SlistNode* pos, SLDateType x,SlistNode**phead)
{if (pos == NULL){printf("目标不存在,操作失败\n");return;}	SlistNode* newnode = buy_slistnode(x);if (*phead==pos)//在第一个节点前插入,没有上一个节点,单独处理{newnode->next = pos;*phead = newnode;return;}SlistNode* cur = *phead;while (cur)//为空意味着找不到{if (cur->next == pos)//找到上一个节点了{break;}cur = cur->next;}if (cur == NULL){printf("目标不存在,操作失败\n");return;}cur->next = newnode;newnode->next = pos;
}

3.测试

#include"链表博客版.h"
void test1()
{SlistNode* plist = NULL;//创建一个链表头slist_pushfront(&plist, 1);//依次将1,2,3头插进链表中slist_pushfront(&plist, 2);//那么链表最后应该是3为头,1为尾slist_pushfront(&plist, 3);print_slist(plist);
}
void test2()
{SlistNode* plist = NULL;slist_pushback(&plist, 10086);//依次尾插10086,666,555,111slist_pushback(&plist, 666);slist_pushback(&plist, 555);slist_pushback(&plist, 111);print_slist(plist);
}
void test3()
{SlistNode* plist = NULL;slist_popfront(&plist);//直接删除,测试报错slist_pushback(&plist, 10086);//依次尾插10086,666,555,111slist_pushback(&plist, 666);slist_pushback(&plist, 555);slist_pushback(&plist, 111);print_slist(plist);slist_popfront(&plist);//删除10086print_slist(plist);slist_popfront(&plist);//删除666print_slist(plist);slist_popfront(&plist);//删除555print_slist(plist);slist_popfront(&plist);//删除111print_slist(plist);
}
void test4()
{SlistNode* plist = NULL;slist_popback(&plist);//直接删除,测试报错slist_pushback(&plist, 10086);//依次尾插10086,666,555,111slist_pushback(&plist, 666);slist_pushback(&plist, 555);slist_pushback(&plist, 111);print_slist(plist);slist_popback(&plist);//删除111print_slist(plist);slist_popback(&plist);//删除555print_slist(plist);slist_popback(&plist);//删除666print_slist(plist);slist_popback(&plist);//删除10086print_slist(plist);slist_popback(&plist);//删除空链表print_slist(plist);
}
void test5()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中slist_pushback(&plist, 2);slist_pushback(&plist, 3);print_slist(plist); SlistNode* pos=slist_find(plist,1);//查找1所在的位置slist_erase_after(pos);//将1之后删除print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_erase_after(pos);//将3之后删除,但是3之后没有节点,删除必定失败print_slist(plist);
}
void test6()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中slist_pushback(&plist, 2);slist_pushback(&plist, 3);print_slist(plist);SlistNode* pos = slist_find(plist, 1);//查找1所在的位置slist_erase(pos, &plist);//将1删除print_slist(plist);	pos = slist_find(plist, 2);//查找2所在的位置slist_erase(pos, &plist);//将2删除print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_erase(pos, &plist);//将3删除print_slist(plist);
}
void test7()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中slist_pushback(&plist, 2);slist_pushback(&plist, 3);SlistNode* pos = slist_find(plist, 1);//查找1所在的位置slist_insert_after(pos, 10086);//在1之后进行插入print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_insert_after(pos, 520);//在3之后进行插入print_slist(plist);pos = slist_find(plist, 10086);//查找10086所在的位置slist_insert_after(pos,9 );//在10086之后进行插入print_slist(plist);
}
void test8()
{SlistNode* plist = NULL;//创建一个链表头slist_pushback(&plist, 1);//通过尾插依次将1,2,3头插进链表中print_slist(plist);SlistNode* pos = slist_find(plist, 1);//查找1所在的位置slist_insert_before(pos, 10086,&plist);//在1之前插入666print_slist(plist);slist_pushback(&plist, 2);slist_pushback(&plist, 3);pos = slist_find(plist, 10086);//查找10086所在的位置slist_insert_before(pos, 666, &plist);//在10086之前插入666print_slist(plist);pos = slist_find(plist, 3);//查找3所在的位置slist_insert_before(pos, 999, &plist);//在3之前插入999print_slist(plist);}
int main()
{test8();
}

 今天的分享到这里就结束了,更新各位友友的来访,祝各位友友前程似锦O(∩_∩)O

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

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

相关文章

【计算机网络】10、ethtool

文章目录 一、ethtool1.1 常见操作1.1.1 展示设备属性1.1.2 改变网卡属性1.1.2.1 Auto-negotiation1.1.2.2 Speed 1.1.3 展示网卡驱动设置1.1.4 只展示 Auto-negotiation, RX and TX1.1.5 展示统计1.1.7 排除网络故障1.1.8 通过网口的 LED 区分网卡1.1.9 持久化配置&#xff08…

QT--day5(网络聊天室、学生信息管理系统)

服务器&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间servernew QTcpServer(this); }Widget::~Widget() {delete ui; …

Codeforces Round 889 (Div. 2)题解

目录 A. Dalton the Teacher题目大意题解思路代码 B. Longest Divisors Interval题目大意题解思路代码 C1. Dual (Easy Version)题目大意题解思路代码 A. Dalton the Teacher 题目链接 题目大意 Dalton是一个班级的老师&#xff0c;这个班级有 n n n个学生&#xff0c;分别…

Kotlin知识点

Kotlin 是 Google 推荐的用于创建新 Android 应用的语言。使用 Kotlin&#xff0c;可以花更短的时间编写出更好的 Android 应用。 基础 Kotlin 程序必须具有主函数&#xff0c;这是 Kotlin 编译器在代码中开始编译的特定位置。主函数是程序的入口点&#xff0c;或者说是起点。…

【C++】类和对象 - 上

目录 1. 面向过程和面向对象初步认识2. 类的引入3. 类的定义4. 类的访问限定符及封装4.1 访问限定符4.2 封装 5. 类的作用域6. 类的实例化7. 类对象模型7.1 如何计算类的大小7.2 类对象的存储方式猜测7.3 结构体内存对齐规则 8. this指针8.1 引出8.2 this指针的特性 总结 1. 面…

打开域名跳转其他网站,官网被黑解决方案(Linux)

某天打开网站&#xff0c;发现进入首页&#xff0c;马上挑战到其他赌博网站。 事不宜迟&#xff0c;不能让客户发现&#xff0c;得马上解决 我的网站跳转到这个域名了 例如网站跳转到 k77.cc 就在你们部署的代码的当前文件夹下面&#xff0c;执行下如下命令 find -type …

Electron 系统通知 Notification 实践指南

系统通知是桌面应用的常见功能&#xff0c;用于给用户发送提醒&#xff08;刷下存在感 &#x1f642;&#xff09;&#xff0c;还能帮定点击事件以便后续的操作。 Electron 自带通知模块&#xff0c;下方代码是一个简单的示例 const { Notification } require(electron)cons…

电脑维护指南:让你的战友始终高效稳定

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

【Ansible】

目录 一、Ansible简介二、ansible 环境安装部署1、管理端安装 ansible 三、ansible 命令行模块&#xff08;重点&#xff09;1&#xff0e;command 模块2&#xff0e;shell 模块3、cron 模块4&#xff0e;user 模块5&#xff0e;group 模块6&#xff0e;copy 模块&#xff08;重…

【论文精读】Self-Attentive Assocative Memory,2020

目录 1 引言2 Outer product attention (OPA)3 Self-attentive Associative Memory (SAM)4 SAM-based Two-Memory Model (STM)4.1 M i M^i Mi写操作4.2 M r M^r Mr读操作4.3 M i M^i Mi读操作和 M r M^r Mr写操作过程4.4 用 M r M^r Mr实现item转移4.5 模型输出 o t o_t ot​…

c语言内存函数的深度解析

本章对 memcpy&#xff0c;memmove&#xff0c;memcmp 三个函数进行详解和模拟实现&#xff1b; 本章重点&#xff1a;3个常见内存函数的使用方法及注意事项并学会模拟实现&#xff1b; 如果您觉得文章不错&#xff0c;期待你的一键三连哦&#xff0c;你的鼓励是我创作的动力…

el-table数据处理

在写表格时遇到&#xff0c;后端返回的数据是对象&#xff0c;并且缺少字段 1.每一条数据加上 一个字段 2.将对象转成数组 以下是数据 {"groupA": {"groupName": null,"orgName": null,"orgId": null,"allPeoper": &quo…

IntersectionObserver实现小程序长列表优化

IntersectionObserver实现小程序长列表优化 关于 IntersectionObserver 思路 这里以一屏数据为单位【一个分页的10条数据&#xff0c;最好大于视口高度】&#xff0c; 监听每一屏数据和视口的相交比例&#xff0c;即用户能不能看到它 只将可视范围的数据渲染到页面上&#x…

Oracle 19c 报ORA-704 ORA-01555故障处理---惜分飞

异常断电导致数据库无法启动,尝试对数据文件进行recover操作,报ORA-00283 ORA-00742 ORA-00312错误,由于redo写丢失无法正常应用 D:\check_db>sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Production on 星期日 7月 30 07:49:19 2023 Version 19.3.0.0.0 Copyrig…

利用读时建模等数据分析能力,实现网络安全态势感知的落地

摘要&#xff1a;本文提出一种基于鸿鹄数据平台的网络安全态势感知系统&#xff0c;系统借助鸿鹄数据平台读时建模、时序处理、数据搜索等高效灵活的超大数据存储和分析处理能力&#xff0c;支持海量大数据存储、分类、统计到数据分析、关联、预测、判断的网络安全态势感知能力…

CentOS7系统Nvidia Docker容器基于TensorFlow2.12测试GPU

CentOS7系统Nvidia Docker容器基于TensorFlow1.15测试GPU 参考我的另一篇博客 1. 安装NVIDIA-Docker的Tensorflow2.12.0版本 1. 版本依赖对应关系&#xff1a;从源代码构建 | TensorFlow GPU 版本Python 版本编译器构建工具cuDNNCUDAtensorflow-2.6.03.6-3.9GCC 7.3.1Ba…

beego通过gorm访问mysql数据库

一、下载golang 二、解压下载包到C盘 三、配置golang系统环境变量 四、进入新建的工作目录C:\project下载并安装beego 五、将新生成的bee.exe所在的路径c:\project\bin加入到系统变量path里面 六、下载并安装mysql 例如在上图中&#xff0c; 选“No thanks,just start my down…

如何在3ds max中创建可用于真人场景的巨型机器人:第 3 部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建腿部装备 步骤 1 打开 3ds Max。 打开在本教程最后一部分中保存的文件。 打开 3ds Max 步骤 2 转到创建> 系统并单击骨骼。 创建>系统 步骤 3 为的 侧视口中的腿&#xff0c;如下图所示…

Java 程序员:本是为了跳槽刷完 1000 道真题,想不到被老板知道直接给我升职

同事&#xff1a;前阵子听说你要跳槽&#xff0c;现在准备得怎么样啊&#xff1f; 程序员 T&#xff1a;不跳了 同事&#xff1a;啊&#xff1f;为什么&#xff1f; 程序员 T&#xff1a;涨薪了呗&#xff1f; 同事&#xff1a;真的吗&#xff1f;涨了多少&#xff1f;你自…

R语言无法调用stats.dll的问题解决方案[补充]

写在前面 在去年10月份&#xff0c;出过一起关于R语言无法调用stats.dll的问题解决方案,今天&#xff08;你看到后是昨天&#xff09;不知道为什么&#xff0c;安装包&#xff0c;一直安装不了&#xff0c;真的是炸裂了。后面再次把R与Rstuido升级。说实话&#xff0c;我是真不…