数据结构单链表

在这里插入图片描述

单链表
1 链表的概念及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链
接次序实现的 。

在我们开始讲链表之前,我们是写了顺序表,顺序表就是类似一个数组的东西,它的存放是连续的,优点有很多,比如支持我们随机访问,连续存放,命中率高,区别于单链表我们可以用类似数组的下标进行访问,这大大的提高我们的效率,但是也有缺点,空间不够就要需要扩容,扩容存在消耗的,头部或者中间位置的插入删除,需要挪动,挪动数据也是存在消耗的。避免频繁扩容,一次一般都是按倍数扩容,可能存在空间扩容。

链表的优点:
按需申请空间,不用释放空间。
头部或者中间位置的插入和删除,不需要挪动数据。
不存在空间浪费。

链表的缺陷:
每一个数据,都要存放一个指针去链表后面节点的地址。
不支持随机访问。

链表的结构

typedef int SLNodedataType;
typedef struct SList
{
	SLNodedataType data;
	struct SList* next;
	
}SLNode;

这个就是我们单链表的基本代码,我们来用图更加清清楚的表示一下它完整的样子。
在这里插入图片描述
这就我们基本的逻辑结构,它前一个的next是存放后面的地址的,这样就能找到我们下一个节点。

单链表使用的时候相比和顺序表比较的话,它的使用不会浪费空间,我们需要一个节点就可以开辟一个节点出来供我们使用。但是它存储就不是连续的了。

那我们现在开始写代码来实现单链表。
单链表
首先我们要创建一个结构体。

typedef int SLNodedataType;
typedef struct SList
{
	SLNodedataType data;
	struct SList* next;
	
}SLNode;

接下来我们首先要打印我们的单链表
在这之前我们应该创建节点,创捷节点很简单,就是按照我们上面的图的前一个存放后面的地址。

//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

那下面就是我们的打印单链表。

void SListPrint(SLNode* plist)
{
	SLNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL");
	printf("\n");

}

我们来测试一下看看效果。

在这里插入图片描述
可以看到我们的单链表也是成功的打印,那接下来就是要写出我们的尾插函数。
写之前我们先来分析分析,首先尾插一个节点进去,那我们是不是要有一个这样的节点,竟然这样就可以写一个创造节点的函数。就叫他CreateSListNode

SLNode* CreateSListNode(SLNodedataType x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

写完这个那我们写一个尾插函数,尾插的时候我们要想一想要传什么地址过去,如果是有数据的话其实我们传一级地址就行,但是如果是空的话,就得传二级,因为我们要改变plist的位置。但是也其实是相当于头插,没节点的时候,总不能在空指针后面插入。那我们写一个 吧。

void SListPushBcak(SLNode** plist, SLNodedataType x)
{
	SLNode*newnode=CreateSListNode(x);
	assert(plist);

	if (*plist == NULL)
	{
		plist = newnode;
	}
	else
	{
		SLNode* tail = *plist;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}

}

看一下我们编译的结果

在这里插入图片描述
最后也是成功的尾插进去,那尾插之后就应该要写一个尾删。
写尾删的时候,我们要先考虑怎么找到最后,这和尾插一样,遍历一遍找到最后一个,然后free掉就行了。

在这里插入图片描述
代码

void SListPopBack(SLNode** plist)
{
	SLNode* tail = *plist;
	SLNode* prev = NULL;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}

这其实就是用了一个双指针的方法找最后一个的前一个,但是我们还需要注意链表不能为空,空了怎么删除啊。所以改进一下。

void SListPopBack(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* tail = *plist;
	SLNode* prev = NULL;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}
void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);
}

不过其实我们也可以不用双指针的办法。
那也整一个玩玩吧


void SListPopBack(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* tail = *plist;
	
	while (tail->next->next != NULL)
	{
		
		tail = tail->next;
	}
	free(tail->next);
	tail->next = NULL;
	

其实道理是一样的,就是找下下一个的节点是不是为空。
尾插写好就是头插,来吧展示。

void SListPushFront(SLNode** plist, SLNodedataType x)
{
	assert(plist);
	SLNode* newnode = CreateSListNode(x);
	if (*plist == NULL)
	{
		*plist = newnode;
	}
	else
	{
		newnode->next = *plist;
		*plist = newnode;
	}

}

其实想明白也不难,接下来就是头删。

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

}
void SListPopFront(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* cur = (*plist)->next;
	free(*plist);
	*plist = cur;
}

我们在写一个查找功能的代码

SLNode* SLFind(SLNode* plist, SLNodedataType x);

查找我们可以返回这个节点,这样就能和其他功能一起用,比如修改数据,或者在任意位置插入和删除。

SLNode* SLFind(SLNode* plist, SLNodedataType x)
{
	SLNode* pos = plist;
	while (pos->data == x)
	{
		return pos;
		pos = pos->next;
	}
}

这是只考虑找到的情况下,但是难免有时候会出现找不到的情况,让我们来看一下吧,写一个找不到情况下和找到情况下的代码。‘

SLNode* SLFind(SLNode* plist, SLNodedataType x)
{
	SLNode* pos = plist;
	while (pos != NULL)
	{
		if (pos->data == x)
		{
			return pos;
		}
		pos = pos->next;
	}
	return NULL;
}

然后我们可以写一个函数来判断有没有找到。

SLNode*pos = SLFind(n1, 111);
	if (pos != NULL)
	{
		printf("找到了\n");
	}
	else
	{
		printf("找不到\n");
	}

我们看完整代码。

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

	SLNode*pos = SLFind(n1, 111);
	if (pos != NULL)
	{
		printf("找到了\n");
	}
	else
	{
		printf("找不到\n");
	}

}

我们如果要找111发现没有找到,因为头删的时候改掉,其实我们竟然这样写了就可以写一个修改的代码,这里就不演示了。
接下来我们要写的是在任意位置删除和插入节点。

void SListPushInsert(SLNode** plist, SLNode* pos, SLNodedataType x)
{
	assert(plist);
	assert(pos);
	SLNode* newnode = CreateSListNode(x);
	if (pos == *plist)
	{
		SListPushFront(plist, x);
	}
	
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;

	}
}

测试代码

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

	SLNode*pos = SLFind(n1,3);
	if (pos != NULL)
	{
		printf("找到了\n");
		SListPushInsert(&n1, pos, 10086);
	}
	else
	{
		printf("找不到\n");
	}
	SListPrint(n1);
}

在任意位置删除

void SListPopInsert(SLNode** plist, SLNode* pos)
{
	assert(plist);
	assert(*plist);
	assert(pos);
	if (*plist == pos)
	{
		SListPopFront(plist);
	}
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

其实还有可以在任意位置后删除,这样更快,就不用找那个位置前一个位置了,这里就不展示了,
完整代码

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int SLNodedataType;
typedef struct SList
{
	SLNodedataType data;
	struct SList* next;
	
}SLNode;


void SListPrint(SLNode* plist);

SLNode* CreateSListNode(SLNodedataType x);


void SListPushBcak(SLNode** plist, SLNodedataType x);

void SListPopBack(SLNode** plist);

void SListPushFront(SLNode** plist, SLNodedataType x);

void SListPopFront(SLNode** plist);

SLNode* SLFind(SLNode* plist, SLNodedataType x);

void SListPushInsert(SLNode** plist, SLNode* pos, SLNodedataType x);

void SListPopInsert(SLNode** plist, SLNode* pos);


#include"SList.h"

void SListPrint(SLNode* plist)
{
	SLNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL");
	printf("\n");

}





SLNode* CreateSListNode(SLNodedataType x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void SListPushBcak(SLNode** plist, SLNodedataType x)
{
	SLNode*newnode=CreateSListNode(x);
	assert(plist);

	if (*plist == NULL)
	{
		plist = newnode;
	}
	else
	{
		SLNode* tail = *plist;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}

}


void SListPopBack(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* tail = *plist;
	SLNode* prev = NULL;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}
//
//void SListPopBack(SLNode** plist)
//{
//	assert(plist);
//	assert(*plist);
//	SLNode* tail = *plist;
//	
//	while (tail->next->next != NULL)
//	{
//		
//		tail = tail->next;
//	}
//	free(tail->next);
//	tail->next = NULL;
//	
//}



void SListPushFront(SLNode** plist, SLNodedataType x)
{
	assert(plist);
	SLNode* newnode = CreateSListNode(x);
	if (*plist == NULL)
	{
		*plist = newnode;
	}
	else
	{
		newnode->next = *plist;
		*plist = newnode;
	}

}

void SListPopFront(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* cur = (*plist)->next;
	free(*plist);
	*plist = cur;
}


//SLNode* SLFind(SLNode* plist, SLNodedataType x)
//{
//	SLNode* pos = plist;
//	while (pos->data == x)
//	{
//		return pos;
//		pos = pos->next;
//	}
//}

SLNode* SLFind(SLNode* plist, SLNodedataType x)
{
	SLNode* pos = plist;
	while (pos != NULL)
	{
		if (pos->data == x)
		{
			return pos;
		}
		pos = pos->next;
	}
	return NULL;
}


void SListPushInsert(SLNode** plist, SLNode* pos, SLNodedataType x)
{
	assert(plist);
	assert(pos);
	SLNode* newnode = CreateSListNode(x);
	if (pos == *plist)
	{
		SListPushFront(plist, x);
	}
	
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;

	}
}

void SListPopInsert(SLNode** plist, SLNode* pos)
{
	assert(plist);
	assert(*plist);
	assert(pos);
	if (*plist == pos)
	{
		SListPopFront(plist);
	}
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

测试主函数的也发一下吧,大家可以不用放一起测试,有点看不过来。

#include"SList.h"

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

	SLNode*pos = SLFind(n1,3);
	if (pos != NULL)
	{
		printf("找到了\n");
		SListPushInsert(&n1, pos, 10086);
	}
	else
	{
		printf("找不到\n");
	}
	SListPrint(n1);
}
int main()
{
	test1();
	return 0;
}

今天的分享就到这里,我们下次再见。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Python批量将Word文件转为PDF文件

说明&#xff1a;在使用Minio服务器时&#xff0c;无法对word文件预览&#xff0c;如果有需要的话&#xff0c;可以将word文件转为pdf文件&#xff0c;再存储到Minio中&#xff0c;本文介绍如果批量将word文件&#xff0c;转为pdf格式的文件&#xff1b; 安装库 首先&#xff…

地址解析协议-ARP

ARP协议 无论网络层使用何种协议&#xff0c;在实际网络的链路上传输数据帧时&#xff0c;最终必须使用硬件地址 地址解析协议&#xff08;Address Resolution Protocol&#xff0c;ARP&#xff09;&#xff1a;完成IP地址到MAC地址的映射&#xff0c;每个主机都有一个ARP高速缓…

图片转换成pdf格式?这几种转换格式方法了解一下

图片转换成pdf格式&#xff1f;将图片转换成PDF格式的好处有很多。首先&#xff0c;PDF格式具有通用性&#xff0c;可以在几乎任何设备上查看。其次&#xff0c;PDF格式可以更好地保护文件&#xff0c;防止被篡改或者复制。此外&#xff0c;PDF格式还可以更好地压缩文件大小&am…

Python Web框架:Django、Flask和FastAPI巅峰对决

今天&#xff0c;我们将深入探讨Python Web框架的三巨头&#xff1a;Django、Flask和FastAPI。无论你是Python小白还是老司机&#xff0c;本文都会为你解惑&#xff0c;带你领略这三者的魅力。废话不多说&#xff0c;让我们开始这场终极对比&#xff01; Django&#xff1a;百…

泰迪大数据挖掘建模平台功能特色介绍

大数据挖掘建模平台面相高校、企业级别用户快速进行数据处理的建模工具。 大数据挖掘建模平台介绍 平台底层算法基于R语言、Python、Spark等引擎&#xff0c;使用JAVA语言开发&#xff0c;采用 B/S 结构&#xff0c;用户无需下载客户端&#xff0c;可直接通过浏览器进行…

docker 容器满了常用处理方法

docker 容器满了常用处理方法 1、运行 df -h 查看剩余磁盘占用情况 2、进入到docker目录 cd /var/lib/docker 3、运行du -h --max-depth1 &#xff08;检索文件的最大深度1&#xff0c;即只检索汇总计算当前目录下的文件&#xff09; 4、进入占用最大的 /containers文件夹&am…

spring入门基本介绍及注入方式---详细介绍

一&#xff0c;spring的简介 Spring是一个开源框架&#xff0c;它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。 提供了许多功能强大且易于使用的特性&#xff0c;使得开发者能够更加轻松地构建可维护且可扩展的应用程序&#xff0c;简单来说: Spring使用基…

Ant Design Vue 下拉框输入框 可以输入 可以查询

Ant Design Vue 下拉框 可以输入 可以查询 直接上代码 效果图 &#xff08;输入内容查询后端 返回下拉的值 &#xff0c;如何查询后端是空的直接 把输入的内容 赋值给 输入框&#xff09; 在这里插入图片描述 <template><div><a-selectv-model.lazy"i…

【论文阅读】基于深度学习的时序预测——Autoformer

系列文章链接 论文一&#xff1a;2020 Informer&#xff1a;长时序数据预测 论文二&#xff1a;2021 Autoformer&#xff1a;长序列数据预测 论文三&#xff1a;2022 FEDformer&#xff1a;长序列数据预测 论文四&#xff1a;2022 Non-Stationary Transformers&#xff1a;非平…

SwiftUI 动画进阶:实现行星绕圆周轨道运动

0. 概览 SwiftUI 动画对于优秀 App 可以说是布帛菽粟。利用美妙的动画我们不仅可以活跃界面元素,更可以单独打造出一整套生动有机的世界,激活无限可能。 如上图所示,我们用动画粗略实现了一个小太阳系:8大行星围绕太阳旋转,而卫星们围绕各个行星旋转。 在本篇博文中,您将…

力扣 213. 打家劫舍 II

题目来源&#xff1a;https://leetcode.cn/problems/house-robber-ii/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a; 对于一个数组&#xff0c;成环的话主要有如下三种情况&#xff1a;&#xff08;1&#xff09;考虑不包含首尾元素&#xff1b;&…

一生一芯4——使用星火应用商店在ubuntu下载QQ、微信、百度网盘

星火应用商店可以非常方便的完成一些应用的下载&#xff0c;下面是官方网址 http://spark-app.store/download 我使用的是intel处理器&#xff0c;无需下载依赖项&#xff0c;直接点击软件本体 我这里下载amd64,根据自己的处理器下载对应版本 sudo apt install ./spark-stor…

性能分析之MySQL慢查询日志分析(慢查询日志)

一、背景 MySQL的慢查询日志是MySQL提供的一种日志记录,他用来记录在MySQL中响应的时间超过阈值的语句,具体指运行时间超过long_query_time(默认是10秒)值的SQL,会被记录到慢查询日志中。 慢查询日志一般用于性能分析时开启,收集慢SQL然后通过explain进行全面分析,一…

Wordcloud | 风中有朵雨做的‘词云‘哦!~

1写在前面 今天可算把key搞好了&#xff0c;不得不说&#x1f3e5;里手握生杀大权的人&#xff0c;都在自己的能力范围内尽可能的难为你。&#x1f602; 我等小大夫也是很无奈&#xff0c;毕竟奔波霸、霸波奔是要去抓唐僧的。 &#x1f910; 好吧&#xff0c;今天是词云&#x…

Mathematica 与 Matlab 常见复杂指令集汇编

Mathematica 常见指令汇编 Mathematica 常见指令 NDSolve 求解结果的保存 sol NDSolve[{y[x] x^2, y[0] 0, g[x] -y[x]^2, g[0] 1}, {y, g}, {x, 0, 1}]; numericSoly sol[[1, 1, 2]]; numericSolg sol[[1, 2, 2]]; data Table[{x, numericSoly[x], numericSolg[x]},…

PG常用SQL

数据库 创建数据库 PostgreSQL 创建数据库可以用以下三种方式&#xff1a; 1、使用 CREATE DATABASE SQL 语句来创建。2、使用 createdb 命令来创建。3、使用 pgAdmin 工具。 CREATE DATABASE 创建数据库 CREATE DATABASE 命令需要在 PostgreSQL 命令窗口来执行&#xff0…

【会议征稿信息】第二届信息学,网络与计算技术国际学术会议(ICINC2023)

2023年第二届信息学&#xff0c;网络与计算技术国际学术会议(ICINC2023) 2023 2nd International Conference on Informatics,Networking and Computing (ICINC 2023) 2023年第二届信息学&#xff0c;网络与计算技术国际学术会议(ICINC2023)将于2023年10月27-29日于中国武汉召…

【第二阶段】kotlin的函数类型作为返回类型

fun main() {//调用,返回的是一个匿名类型&#xff0c;所以info就是一个匿名函数val infoshow("",0)//info接受的返回值为匿名类型&#xff0c;此时info就是一个匿名函数println(info("kotlin",20)) }//返回类型为一个匿名函数的返回类型fun show(name:Str…

内网穿透-外远程连接中的RabbitMQ服务

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

音视频FAQ(三):音画不同步

摘要 本文介绍了音画不同步问题的五个因素&#xff1a;编码和封装阶段、网络传输阶段、播放器中的处理阶段、源内容产生的问题以及转码和编辑。针对这些因素&#xff0c;提出了相应的解决方案&#xff0c;如使用标准化工具、选择强大的传输协议、自适应缓冲等。此外&#xff0…