【C项目】无头单向不循环链表

news2024/11/27 16:37:02

简介:本系列博客为C项目系列内容,通过代码来具体实现某个经典简单项目
适宜人群:已大体了解C语法同学
作者留言:本博客相关内容如需转载请注明出处,本人学疏才浅,难免存在些许错误,望留言指正
作者博客链接:睡觉待开机

下面是本项目的大体思路梳理:
在这里插入图片描述

全部接口一览:

在这里插入图片描述

void SLTPrint(SLTNode* phead);//打印
void SLTPushBack(SLTNode** pphead,SLTDateType x);//尾插
void SLTPushiFront(SLTNode** pphead, SLTDateType x);//头插
void SLTPopBack(SLTNode** pphead);//尾删
void SLTPopFront(SLTNode** pphead);//头删
void SLTInsert(SLTNode** pphead,SLTNode* pos,SLTDateType x);//任意位置之前插入
SLTNode* SLTFind(SLTNode** pphead, SLTDateType x);//查找接口
void SLTInsertAfter(SLTNode* pos, SLTDateType x);//任意位置之后插入
void SLTErase(SLTNode** pphead, SLTNode* pos);//删除pos指向的节点
void SLTEraseAfter(SLTNode* pos);//删除pos指向之后的节点
void SLTDestroy(SLTNode** pphead);//销毁链表接口

1.创建链表的结构体

在这里插入图片描述
在这里插入图片描述

//定义单链表结构体
#define SLTDateType int
typedef struct SListNode
{
	SLTDateType date;//每个节点的数据
	struct SListNode* next;//每个节点存储下一个节点的地址
}SLTNode;

2.打印链表的接口实现

首先制造一些节点并进行相连操作
在这里插入图片描述
打印函数实现的思路:
在这里插入图片描述
在这里插入图片描述

void SLTPrint(SLTNode* phead)
{
	//定义一个新的指针
	SLTNode* pcur = phead;

	//循环打印即可,什么时候停止?pcur不指向空便不停止
	while (pcur)
	{
		//打印数据
		printf("%d->", pcur->date);
		//更新指针
		pcur = pcur->next;
	}

	//为了完善,我给最后也加一个NULL
	printf("NULL\n");
}

3.尾插接口实现

思路:定义一个新指针,找到原链表的尾节点,找到了接上即可。
在这里插入图片描述
这里为什么要分类进行讨论?这由思路决定的,因为如果是空链表的情况下,ptail->next根本就是错误的,因为不存在。
在这里插入图片描述
在这里插入图片描述
新空间开辟接口:
在这里插入图片描述

void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);

	//申请一块新的空间
	SLTNode* newnode = SLTBuyNode(x);
	//分两种情况
	//链表为空
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else//链表不为空
	{
		SLTNode* ptail = *pphead;//用于找到链表的尾节点
		while (ptail->next)
		{
			ptail = ptail->next;
		}//找到尾节点
		ptail->next = newnode;//给他接上
	}
}

SLTNode* SLTBuyNode(SLTDateType x)
{
	//申请一块新的空间
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	//放内容
	newnode->date = x;
	newnode->next = NULL;
	//返回地址
	return newnode;
}

4.头插接口实现

思路:
在这里插入图片描述
在这里插入图片描述
尾插需要分情况讨论而头插怎么不需要呢?还是思路决定的,这个思路没有用到ptail->next所以就不需要考虑空链表的情况

void SLTPushiFront(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);

	//申请一块新的空间
	SLTNode* newnode = SLTBuyNode(x);
	//把原来第一个结点的地址交给新节点的next
	newnode->next = *pphead;
	*pphead = newnode;//把头部指针更新一下
}

5.尾删接口实现

思路:
在这里插入图片描述
在这里插入图片描述
这里为什么要分只有一个节点和多个节点的不同情况?因为涉及到prev问题如果是只有一个节点,ptail指向第一个节点,那prev指针指向哪里?所以要对只有一个节点的链表单独进行处理。

void SLTPopBack(SLTNode** pphead)
{
	//检验
	assert(pphead);//原本的指针不能是空
	assert(*pphead);//传过来的不能是空指针给我删除啊

	//删除
	//这里分两种情况
	//1.只有一个节点的情况
	if (*pphead == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	else//多个节点的情况
	{
		//需要找到最后一个节点和倒数第二个节点
		//最后一个节点是为了释放空间
		//倒数第二个节点是为了把他的next部分置为空
		SLTNode* ptail = *pphead;
		SLTNode* prev = *pphead;
		while (ptail->next)
		{
			prev = ptail;
			ptail = ptail->next;
		}

		//第二个节点next置为空
		prev->next = NULL;
		//销毁第一个节点
		free(ptail);
		ptail = NULL;
	}
}

6.头删接口的实现

思路:
在这里插入图片描述
在这里插入图片描述

void SLTPopFront(SLTNode** pphead)
{
	//检验
	assert(pphead);//检验你别给我传个空
	assert(*pphead);//检验链表不为空,空链表删除什么?

	//开始准备删除
	SLTNode* next = (*pphead)->next;//记录一下要接上的地址
	free(*pphead);//释放第一个节点
	*pphead = next;
}

7.查找接口实现

查找接口是做什么的呢?找一个节点的地址的。
思路实现:
在这里插入图片描述
在这里插入图片描述

SLTNode* SLTFind(SLTNode** pphead, SLTDateType x)
{
	//检查
	assert(pphead);//别传空指针进来
	//这里可以传空链表吗?可以!顶多找不到给你返回一个NULL嘛

	//遍历链表
	SLTNode* pcur = *pphead;
	while (pcur)//当pcur找到NULL时候就会停止
	{
		if (pcur->date == x)
		{
			return pcur;//满足条件,返回该节点的地址
		}
		pcur = pcur->next;//更新指针
	}
	//如果什么都没有找到的话,是不是会不太合适\
	// 所以我们规定如果没有找到,返回NULL地址

	return NULL;
}

8.在指定位置之前插入数据

在这里插入图片描述
在这里插入图片描述

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	//检验
	assert(pphead);//传入地址不得为空
	assert(pos);//pos不得为空
	assert(*pphead);//要加上链表不得为空,\
	这是因为pos是链表的一个节点的地址,如 \
    果链表不存在,那么pos也会不存在

	//这里要分情况进行处理
	//1.pos刚好是头节点
	if (pos == *pphead)
	{
		//直接调用头插
		SLTPushiFront(pphead,x);
		return;
	}
	else//2.如果pos不是头节点
	{
		SLTNode* prev = *pphead;
		//让prev找到pos之前的节点的地址
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		
		SLTNode* newnode = SLTBuyNode(x);//申请空间
		prev->next = newnode;//把新空间链接到我们前一个节点
		newnode->next = pos;//把新空间与pos指向的空间链接在一起
	}
}

9.在指定位置之后插入数据的接口实现

思路:
在这里插入图片描述
在这里插入图片描述
思考:上面说的关联新节点的错误是如何引起的呢?
答:因为新节点的后面的节点的地址表示是靠的pos->next

void SLTInsertAfter(SLTNode* pos, SLTDateType x)//之后
{
	//检查
	assert(pos);
	
	//申请空间
	SLTNode* newnode = SLTBuyNode(x);

	//关联新节点的错误写法,原因:pos值的改变
	//pos->next = newnode;
	//newnode->next = pos->next;

	//关联新节点的正确写法:
	//先接后面,再接前面
	newnode->next = pos->next;
	pos->next = newnode;

}

10.删除指定位置的节点

思路:
在这里插入图片描述

在这里插入图片描述

void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	//检查
	assert(pphead);//不得传空
	assert(*pphead);//不得为空链表
	assert(pos);

	//pos刚好是头节点的情况,头删
	if (*pphead == pos)
	{
		//头删
		SLTPopFront(pphead);
		return;
	}
	//如果不是头节点
	else {
		//找到pos之前的节点
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}

}

11.删除指定位置之后的节点接口实现

思路:
在这里插入图片描述
在这里插入图片描述

void SLTEraseAfter(SLTNode* pos)
{
	//检查
	assert(pos);//传过来的地址不可以为空
	assert(pos->next);//传过来的地址的下一个地址不得为空

	SLTNode* del = pos->next;//记录要删除的节点的地址
	pos->next = pos->next->next;//更新pos中next的地址
	free(del);//释放空间
	del = NULL;//临时指针及时置为空
}

12.销毁链表接口

思路:
在这里插入图片描述
在这里插入图片描述

void SLTDestroy(SLTNode** pphead)
{
	assert(pphead);//传过来的指针不得为空
	assert(*pphead);//链表不得为空,空链表不用销毁

	//创建遍历指针
	SLTNode* pcur = *pphead;
	//循环销毁
	while (pcur)//啥时候停止?pcur指向NULL
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	//最后把头指针也置为NULL
	*pphead = NULL;
}

全部代码合集

//SList.h
#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>

//定义单链表结构体
#define SLTDateType int
typedef struct SListNode
{
	SLTDateType date;//每个节点的数据
	struct SListNode* next;//每个节点存储下一个节点的地址
}SLTNode;


void SLTPrint(SLTNode* phead);//打印
void SLTPushBack(SLTNode** pphead,SLTDateType x);//尾插
void SLTPushiFront(SLTNode** pphead, SLTDateType x);//头插
void SLTPopBack(SLTNode** pphead);//尾删
void SLTPopFront(SLTNode** pphead);//头删
void SLTInsert(SLTNode** pphead,SLTNode* pos,SLTDateType x);//任意位置之前插入
SLTNode* SLTFind(SLTNode** pphead, SLTDateType x);//查找接口
void SLTInsertAfter(SLTNode* pos, SLTDateType x);//任意位置之后插入
void SLTErase(SLTNode** pphead, SLTNode* pos);//删除pos指向的节点
void SLTEraseAfter(SLTNode* pos);//删除pos指向之后的节点
void SLTDestroy(SLTNode** pphead);//销毁链表接口
//SList.c
#include"SList.h"

SLTNode* SLTBuyNode(SLTDateType x)
{
	//申请一块新的空间
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	//放内容
	newnode->date = x;
	newnode->next = NULL;
	//返回地址
	return newnode;
}

SLTNode* SLTFind(SLTNode** pphead, SLTDateType x)
{
	//检查
	assert(pphead);//别传空指针进来
	//这里可以传空链表吗?可以!顶多找不到给你返回一个NULL嘛

	//遍历链表
	SLTNode* pcur = *pphead;
	while (pcur)//当pcur找到NULL时候就会停止
	{
		if (pcur->date == x)
		{
			return pcur;//满足条件,返回该节点的地址
		}
		pcur = pcur->next;//更新指针
	}
	//如果什么都没有找到的话,是不是会不太合适\
	// 所以我们规定如果没有找到,返回NULL地址

	return NULL;
}

void SLTPrint(SLTNode* phead)
{
	//定义一个新的指针
	SLTNode* pcur = phead;

	//循环打印即可,什么时候停止?pcur不指向空便不停止
	while (pcur)
	{
		//打印数据
		printf("%d->", pcur->date);
		//更新指针
		pcur = pcur->next;
	}

	//为了完善,我给最后也加一个NULL
	printf("NULL\n");
}

void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);

	//申请一块新的空间
	SLTNode* newnode = SLTBuyNode(x);
	//分两种情况
	//链表为空
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else//链表不为空
	{
		SLTNode* ptail = *pphead;//用于找到链表的尾节点
		while (ptail->next)
		{
			ptail = ptail->next;
		}//找到尾节点
		ptail->next = newnode;//给他接上
	}
}

void SLTPushiFront(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);

	//申请一块新的空间
	SLTNode* newnode = SLTBuyNode(x);
	//把原来第一个结点的地址交给新节点的next
	newnode->next = *pphead;
	*pphead = newnode;//把头部指针更新一下
}

void SLTPopBack(SLTNode** pphead)
{
	//检验
	assert(pphead);//原本的指针不能是空
	assert(*pphead);//传过来的不能是空指针给我删除啊

	//删除
	//这里分两种情况
	//1.只有一个节点的情况
	if (*pphead == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	else//多个节点的情况
	{
		//需要找到最后一个节点和倒数第二个节点
		//最后一个节点是为了释放空间
		//倒数第二个节点是为了把他的next部分置为空
		SLTNode* ptail = *pphead;
		SLTNode* prev = *pphead;
		while (ptail->next)
		{
			prev = ptail;
			ptail = ptail->next;
		}

		//第二个节点next置为空
		prev->next = NULL;
		//销毁第一个节点
		free(ptail);
		ptail = NULL;
	}
}

void SLTPopFront(SLTNode** pphead)
{
	//检验
	assert(pphead);//检验你别给我传个空
	assert(*pphead);//检验链表不为空,空链表删除什么?

	//开始准备删除
	SLTNode* next = (*pphead)->next;//记录一下要接上的地址
	free(*pphead);//释放第一个节点
	*pphead = next;
}


void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	//检验
	assert(pphead);//传入地址不得为空
	assert(pos);//pos不得为空
	assert(*pphead);//要加上链表不得为空,
	//这是因为pos是链表的一个节点的地址,如 
    //果链表不存在,那么pos也会不存在

	//这里要分情况进行处理
	//1.pos刚好是头节点
	if (pos == *pphead)
	{
		//直接调用头插
		SLTPushiFront(pphead,x);
		return;
	}
	else//2.如果pos不是头节点
	{
		SLTNode* prev = *pphead;
		//让prev找到pos之前的节点的地址
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		
		SLTNode* newnode = SLTBuyNode(x);//申请空间
		prev->next = newnode;//把新空间链接到我们前一个节点
		newnode->next = pos;//把新空间与pos指向的空间链接在一起
	}
}


void SLTInsertAfter(SLTNode* pos, SLTDateType x)//之后
{
	//检查
	assert(pos);
	
	//申请空间
	SLTNode* newnode = SLTBuyNode(x);

	//关联新节点的错误写法,原因:pos值的改变
	//pos->next = newnode;
	//newnode->next = pos->next;

	//关联新节点的正确写法:
	//先接后面,再接前面
	newnode->next = pos->next;
	pos->next = newnode;

}

void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	//检查
	assert(pphead);//不得传空
	assert(*pphead);//不得为空链表
	assert(pos);

	//pos刚好是头节点的情况,头删
	if (*pphead == pos)
	{
		//头删
		SLTPopFront(pphead);
		return;
	}
	//如果不是头节点
	else {
		//找到pos之前的节点
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}

}


void SLTEraseAfter(SLTNode* pos)
{
	//检查
	assert(pos);//传过来的地址不可以为空
	assert(pos->next);//传过来的地址的下一个地址不得为空

	SLTNode* del = pos->next;//记录要删除的节点的地址
	pos->next = pos->next->next;//更新pos中next的地址
	free(del);//释放空间
	del = NULL;//临时指针及时置为空
}

void SLTDestroy(SLTNode** pphead)
{
	assert(pphead);//传过来的指针不得为空
	assert(*pphead);//链表不得为空,空链表不用销毁

	//创建遍历指针
	SLTNode* pcur = *pphead;
	//循环销毁
	while (pcur)//啥时候停止?pcur指向NULL
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	//最后把头指针也置为NULL
	*pphead = NULL;
}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

void test1()
{
	//头指针
	SLTNode* phead = NULL;
	//造一点结点
	SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
	node1->date = 1;
	SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
	node2->date = 2;
	SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
	node3->date = 3;
	SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
	node4->date = 4;
	SLTNode* node5 = (SLTNode*)malloc(sizeof(SLTNode));
	node5->date = 5;

	//链接这些节点
	phead = node1;
	node1->next = node2;
	node2->next = node3;
	node3->next = node4;
	node4->next = node5;
	node5->next = NULL;

	//调用一下打印函数
	SLTPrint(phead);
}

void test2()
{
	SLTNode* phead = NULL;

	SLTPushBack(&phead,6);
	SLTPrint(phead);

	SLTPushiFront(&phead,0);
	SLTPushiFront(&phead,1);
	SLTPushiFront(&phead,2);
	SLTPushiFront(&phead,3);
	SLTPushiFront(&phead,4);
	SLTPushiFront(&phead,5);
	SLTPrint(phead);//5->4->3->2->1->0->6->NULL

	SLTPopBack(&phead);
	SLTPrint(phead);//5->4->3->2->1->0->NULL
	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPrint(phead);//1->0->NULL
	
	SLTNode* find = SLTFind(&phead,1);
	SLTInsert(&phead, find, 2);
	SLTPrint(phead);//2->1->0->NULL
	SLTInsertAfter(find, 8);
	SLTPrint(phead);//2->1->8->0->NULL
	
	SLTEraseAfter(find);
	SLTPrint(phead);//2->8->0->NULL

	SLTDestroy(&phead);
	SLTPrint(phead);//NULL

}

int main()
{
	//测试我的打印函数
	//test1();
	//测试我的插入与删除函数
	test2();
	return 0;
}

完。

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

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

相关文章

ai图片放大老照片ai处理ps学习

老照片处理 1.bigjpg&#xff1a;AI人工智能图片放大 体验后评价&#xff1a;快速稳定 2.jpgHD&#xff1a;同bigjpg 另支持老照片上色 付费可用&#xff1a;破损修复&#xff0c;魔法动态照片 3.bigmp4&#xff1a;ai视频无损放大 4.jpgrm&#xff1a;ai擦除 利用2023年最先进…

Java入门及环境变量

文章目录 1.1 Java简介1.2 JDK的下载和安装1.3 第一个程序1.4 常见问题1.5 常用DOS命令1.6 Path环境变量 1.1 Java简介 下面我们正式进入Java的学习&#xff0c;在这里&#xff0c;大家第一个关心的问题&#xff0c;应该就是 Java 是什么&#xff0c;我们一起来看一下&#xf…

VMware Workstation 17安装教程:创建虚拟机

虚拟机软件的管理界面 新建虚拟机向导 设置硬件兼容性 设置系统的安装来源 选择操作系统的版本 未完待续&#xff0c;明天继续更新&#xff0c;如有疑问&#xff0c;点击链接加入群聊【信创技术交流群】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kEjDhISXNgJlM…

CV论文--2024.2.19

1、Self-Play Fine-Tuning of Diffusion Models for Text-to-Image Generation 中文标题&#xff1a;自我对弈微调扩散模型&#xff0c;用于文本到图像生成 简介&#xff1a;在生成人工智能&#xff08;GenAI&#xff09;领域&#xff0c;微调扩散模型仍然是一个未被充分探索的…

App启动优化笔记 1

app大致的启动流程。有Launcher进程,system_server进程,zygote进程,APP进程。 Launcher进程:启动activity来启动应用 system_server进程:(ams是其中的一个binder):发送一个socket消息给Zygote。 zygote进程:收到消息后,fork新的进程,---》app进程启动 APP进程:…

Google发布能自我学习能力的Gemini 1.5

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 这波ai浪潮&#xff0c;进化的越来越强大和实用了&#xff0c;OpenAi刚发布了文生视频大模型Sora。而Google发布能了具有自我学习能力的Gemini 1.5。 Google 的大模型以及 AI 聊天机器人都采用 Gemini 这一名称。前…

唯一客服系统:Golang开发客服系统源码,支持网页,H5,APP,微信小程序公众号等接入,商家有PC端管理和H5,可以配置AI智能回复(搭建部署教程)

本系统采用Golang Gin框架GORMMySQLVueElementUI开发的独立高性能在线客服系统。客服系统访客端支持PC端、移动端、小程序、公众号中接入客服&#xff0c;利用超链接、网页内嵌、二维码、定制对接等方式让网上所有通道都可以快速通过本系统联系到商家。 服务端可编译为二进制程…

微软和OpenAI将检查AI聊天记录,以寻找恶意账户

据国外媒体报道&#xff0c;大型科技公司及其附属的网络安全、人工智能产品很可能会推出类似的安全研究&#xff0c;尽管这会引起用户极度地隐私担忧。大型语言模型被要求提供情报机构信息&#xff0c;并用于帮助修复脚本错误和开发代码以侵入系统&#xff0c;这将很可能会成为…

【JVM篇】什么是运行时数据区

文章目录 &#x1f354;什么是运行时数据区⭐程序计数器⭐栈&#x1f50e;Java虚拟机栈&#x1f388;栈帧的内容 &#x1f50e;本地方法栈 ⭐堆⭐方法区 &#x1f354;什么是运行时数据区 运行时数据区指的是jvm所管理的内存区域&#xff0c;其中分为两大类 线程共享&#xf…

Unity导出Android studio项目遇到的aar无法打包问题

Android Studio 接入现有aar 前因,开发过程中,发现Unity打包出来的android包,带有aar,随着android studio打包的过程中,发现要么提示aar要从网络下载,下载不到,要么提示当前aar不能直接在本地引入(玄学,之前一直不会),会导致损坏。 原因,Android studio版本高,An…

OpenCV中inRange函数

在OpenCV中&#xff0c;inRange函数用于根据颜色范围从图像中提取特定的颜色区域。这个函数检查输入图像中的每个像素&#xff0c;如果像素值位于指定的范围内&#xff0c;则在输出图像&#xff08;或掩码&#xff09;中对应位置的像素被设置为白色&#xff08;或者说是255&…

救命~女儿这样穿也太好看了吧

充满青春活力感的 一件小熊针织学院风开衫 小编墙裂推荐哦早春天气微凉 这件抗起球包芯纱材质的开衫 厚度就刚刚好里面随意搭件T恤来穿 上学还是日常出游穿都很合适

传奇手游白日门【天玺996】win架设服务端+双端+GM授权后台+详细教程

资源下载地址&#xff1a;传奇手游白日门【天玺996】win架设服务端双端GM授权后台详细教程 - 海盗空间

数据结构1.0(基础)

近java的介绍&#xff0c; 文章目录 第一章、数据结构1、数据结构 &#xff1f;2、常用的数据结构数据结构&#xff1f; 逻辑结构and物理结构 第二章、数据结构基本介绍2.1、数组&#xff08;Array&#xff09;2.2、堆栈&#xff08;Stack&#xff09;2.3、队列&#xff08;Que…

基于Gost工具的ICMP隐蔽隧道通信分析

1.概述 近期&#xff0c;观成科技安全研究团队在现网中检测到了利用Gost工具实现加密隧道的攻击行为。Gost是一款支持多种协议的隧道工具&#xff0c;使用go语言编写。该工具实现了多种协议的隧道通信方法&#xff0c;例如TCP/UDP协议&#xff0c;Websocket&#xff0c;HTTP/2…

MySQL之select查询

华子目录 SQL简介SQL语句分类SQL语句的书写规范SQL注释单行注释多行注释 select语句简单的select语句select的算数运算select 要查询的信息 from 表名;查询表字段查询常量查询表达式查询函数 查询定义别名as安全等于<>去重distinct连接字段concat 模糊查询运算符比较运算…

电商数据分析工具(京东淘宝电商数据):电商运营过程中为什么要做数据分析?电商企业如何做好数据分析?

众所周知&#xff0c;电商企业进行数据分析是电商运营中的重要一环&#xff0c;电商数据分析是企业持续改进业务流程、提高运营效率、增加收入和利润的关键。 通过深入的数据分析&#xff0c;电商企业能够更有效地响应市场需求、提高客户满意度&#xff0c;最终实现可持续增长…

如何图片无损放大?几个无损放大图片分享

在数字化时代&#xff0c;图片已经成为我们生活中不可或缺的一部分。从社交媒体上的分享&#xff0c;到专业摄影作品的展示&#xff0c;再到网页设计和平面广告的制作&#xff0c;图片的质量往往直接影响到我们的视觉体验和信息传达的效果。然而&#xff0c;有时候&#xff0c;…

选择现货白银交易平台后要怎么做?

进入现货白银市场&#xff0c;选择现货白银交易平台是投资者首先要面对的问题。然而&#xff0c;有投资者认为解决了这个问题&#xff0c;往后就一帆风顺了&#xff0c;这样投资者把现货白银交易想的太简单了。如果真这么简单&#xff0c;岂不是很多投资者都可以获得盈利&#…

快排——OJ题

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、颜色划分1、题目讲解2、算法原理3、代码实现 二、排序数组1、题目讲解2、算法原理3、代码…