第 3 章 栈和队列(顺序栈,算法 3.1 、3.2、3.4)

news2025/1/13 2:49:54

1.  示例代码:

1) status.h

/* DataStructure 预定义常量和类型头文件 */

#ifndef STATUS_H
#define STATUS_H

/* 函数结果状态码 */
#define TRUE 					1			/* 返回值为真 */
#define FALSE 					0			/* 返回值为假 */
#define RET_OK 					0			/* 返回值正确 */
#define INFEASIABLE    		   	2			/* 返回值未知 */
#define ERR_MEMORY     		   	3			/* 访问内存错 */
#define ERR_NULL_PTR   			4			/* 空指针错误 */
#define ERR_MEMORY_ALLOCATE		5			/* 内存分配错 */
#define ERR_NULL_STACK			6			/* 栈元素为空 */
#define ERR_PARA				7			/* 函数参数错 */
#define ERR_OPEN_FILE			8			/* 打开文件错 */
typedef int Status;							/* Status 是函数的类型,其值是函数结果状态代码,如 OK 等 */
typedef int Bollean;						/* Boolean 是布尔类型,其值是 TRUE 或 FALSE */

#endif // !STATUS_H

2) sqStack.h

/* 栈的顺序存储表示头文件 */

#ifndef SQSTACK_H
#define SQSTACK_H

#define STACK_INIT_SIZE 10 		/* 存储空间初始分配量 */
#define STACKINCREMENT 2 		/* 存储空间分配增量 */

#include "status.h"

typedef int SElemType;

typedef struct SqStack
{
	SElemType* base; 			/* 在栈构造之前和销毁之后,base的值为NULL */
	SElemType* top; 			/* 栈顶指针 */
	int stackSize; 				/* 当前已分配的存储空间,以元素为单位 */
} SqStack; 						/* 顺序栈 */

/* 构造一个空栈 S */
Status InitStack(SqStack* S);

/* 销毁栈 S */
void DestroyStack(SqStack* S);

/* 把 S 置为空栈 */
void ClearStack(SqStack* S);

/* 若栈 S 为空栈,则返回 TRUE,否则返回 FALSE */
Status StackEmpty(SqStack S);

/* 返回 S 的元素个数,即栈的长度 */
int StackLength(SqStack S);

/* 若栈不空,则用 e 返回 S 的栈顶元素,并返回 OK;否则返回 ERROR */
Status GetTop(SqStack S, SElemType* e);

/* 插入元素 e 为新的栈顶元素 */
Status Push(SqStack* S, SElemType e);

/* 若栈不空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK;否则返回 ERROR */
Status Pop(SqStack* S, SElemType* e);

/* 从栈底到栈顶依次对栈中每个元素调用函数 visit() */
void StackTraverse(SqStack S, void(*Visit)(SElemType));

#endif

3)  sqStack.c

/* 栈的顺序存储表示源文件 */

#include "sqStack.h"
#include "status.h"
#include <stdlib.h>
#include <stdio.h>

/* 构造一个空栈 S */
Status InitStack(SqStack* S)
{
	(*S).base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!(*S).base) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	(*S).top = (*S).base;
	(*S).stackSize = STACK_INIT_SIZE;

	return RET_OK;
}

/* 销毁栈 S */
void DestroyStack(SqStack* S)
{
	free((*S).base);
	(*S).base = NULL;
	(*S).top = NULL;
	(*S).stackSize = 0;
}

/* 把 S 置为空栈 */
void ClearStack(SqStack* S)
{
	(*S).top = (*S).base;
}

/* 若栈 S 为空栈,则返回 TRUE,否则返回 FALSE */
Status StackEmpty(SqStack S)
{
	return (S.top == S.base) ? TRUE : FALSE;
}

/* 返回 S 的元素个数,即栈的长度 */
int StackLength(SqStack S)
{
	return (int)(S.top - S.base);
}

/* 若栈不空,则用 e 返回 S 的栈顶元素,并返回 OK;否则返回 ERROR */
Status GetTop(SqStack S, SElemType* e)
{
	if (S.top > S.base) {
		*e = *(S.top - 1);
		return RET_OK;
	}

	printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_STACK);

	return ERR_NULL_STACK;
}

/* 插入元素 e 为新的栈顶元素 */
Status Push(SqStack* S, SElemType e)
{
	if (((*S).top - (*S).base) == (*S).stackSize) {
		(*S).base = (SElemType*)realloc((*S).base, (unsigned long long)(((*S).stackSize) + STACKINCREMENT) * sizeof(SElemType));
		if (!(*S).base) {
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);
			return ERR_MEMORY_ALLOCATE;
		}

		(*S).top = (*S).base + (*S).stackSize;
		(*S).stackSize += STACKINCREMENT;
	}

	*((*S).top)++ = e;

	return RET_OK;
}

/* 若栈不空,则删除 S 的栈顶元素,用 e 返回其值,并返回 OK;否则返回 ERROR */
Status Pop(SqStack* S, SElemType* e)
{
	if ((*S).top == (*S).base) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	*e = *(--(*S).top);

	return RET_OK;
}

/* 从栈底到栈顶依次对栈中每个元素调用函数 visit() */
void StackTraverse(SqStack S, void(*Visit)(SElemType))
{
	while (S.top > S.base) {
		Visit(*S.base++);
	}
}

4) auxiliary.h

/* 辅助函数头文件 */

#ifndef AUXILIARY_H
#define AUXILIARY_H

#include "sqStack.h"

/* 打印栈元素 */
void Print(SElemType e);

#endif // !AUXILIARY_H

5) auxiliary.c

/* 辅助函数实现源文件 */

#include "auxiliary.h"
#include <stdio.h>

/* 打印栈元素 */
void Print(SElemType e)
{
	printf("%d ", e);
}

6) algorithm.h

/* 算法定义头文件 */
#ifndef ALGORITHM_H
#define ALGORITHM_H

#include "sqStack.h"
#include "status.h"

/* 算法 3.1, 对于输入的任意一个非负 10 进制整数,打印输出与其等值的 8 进制数 */
void Conversion(unsigned int num);

/* 算法 3.1<2>, 对于输入的任意一个非负 10 进制整数,打印输出与其等值的 16 进制数 */
void TransOctalToHexa(unsigned int num);

/* 对于输入的任意一个字符串,检验括号 ()、[] 是否配对 */
Status BracketMatchCheck(char str[], int strLength);

/* 算法 3.2, 利用字符栈 S,从终端接收一行并送至调用过程的数据区 */
Status LineEdit(void);

/* 算法 3.4, 算术表达式求值的算符优先算法。设 OPTR 和 OPND 分别为运算符栈和运算数栈 */
SElemType CaculateExpression(void);

/* 算法 3.4<2>, 算术表达式求值的算符优先算法。设 OPTR 和 OPND 分别为运算符栈和运算数栈
   对算法 3.4 的优化,解除输入限制 */
SElemType CaculateExpression2(void);

#endif // !ALGORITHM_H

7) algorithm.c

/* 算法实现源文件 */

#include "algorithm.h"
#include "sqStack.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* 算法 3.1, 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 */
void Conversion(unsigned int num)
{
	SqStack S;
	InitStack(&S);

	/* step 1: 入栈 */
	while (num) {
		Push(&S, num % 8);
		num /= 8;
	}

	/* step 2: 出栈 */
	SElemType e;
	while (!StackEmpty(S)) {
		Pop(&S, &e);
		printf("%d", e);
	}
}

/* 算法 3.1<2>, 对于输入的任意一个非负 10 进制整数,打印输出与其等值的 16 进制数 */
void TransOctalToHexa(unsigned int num)
{
	SqStack S;
	InitStack(&S);

	/* step 1: 入栈 */
	while (num) {
		Push(&S, num % 16);
		num /= 16;
	}

	/* step 2: 出栈 */
	SElemType e;
	printf("0X");
	while (!StackEmpty(S)) {
		Pop(&S, &e);
		if (e <= 9) {
			printf("%d", e);
		} else {
			printf("%c", e + 55);
		}
	}
}

/* 对于输入的任意一个字符串,检验括号 ()、[] 是否配对 */
Status BracketMatchCheck(char str[], int strLength)
{
	if (str == NULL) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR);
		return FALSE;
	}

	if ((int)strlen(str) != strLength) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
		return FALSE;
	}

	SqStack S = { 0 };
	int ret = InitStack(&S);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
		return FALSE;
	}

	char* p = str;
	SElemType e = 0;
	while (*p) {
		switch (*p) {
			case '(':
			case '[':
				ret = Push(&S, *p++);
				if (ret != RET_OK) {
					printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
					return FALSE;
				}
				break;
			case ')':
			case ']':
				if (!StackEmpty(S)) {
					ret = Pop(&S, &e);
					if (ret != RET_OK) {
						printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
						return FALSE;
					}

					if (((*p == ')') && (e != '(')) || ((*p == ']') && (e != '['))) {
						return FALSE;
					} else {
						++p;
						break;
					}
				} else {
					return FALSE;
				}
			default:
				break;
		}
	}

	if (StackEmpty(S)) {
		return TRUE;
	}

	return FALSE;
}

/* 算法 3.2, 利用字符栈 S,从终端接收一行并送至调用过程的数据区 */
Status LineEdit(void)
{
	SqStack S = { 0 };
	int ret = InitStack(&S);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
		return FALSE;
	}

	FILE* fp = NULL;
	errno_t err_ret = fopen_s(&fp, "ED.DAT", "w");
	if (err_ret != 0) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_OPEN_FILE);
		return FALSE;
	}

	SElemType ch = getchar();
	while (ch != '$') {
		while ((ch != '$') && (ch != '\n')) {
			switch (ch) {
			case '#':
				ret = Pop(&S, &ch);
				if (ret != RET_OK) {
					printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
					return FALSE;
				}
				break;
			case '@':
				ClearStack(&S);
				break;
			default:
				ret = Push(&S, ch);
				if (ret != RET_OK) {
					printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
					return FALSE;
				}
			}

			ch = getchar();
		}

		SElemType* sE = S.base;
		while (S.top > sE) {
			fputc(*sE++, fp);
		}

		ClearStack(&S);
		if (ch != '$') {
			fputc('\n', fp);
			ch = getchar();
		}
	}

	DestroyStack(&S);
	fclose(fp);

	return TRUE;
}

/* 获取 sE1 与 sE2 的优先级关系 */
SElemType OperPriority(SElemType sE1, SElemType sE2)
{
	SElemType ret = '\0';
	switch (sE2) {
	case '+':
	case '-':
		if ((sE1 == '(') || (sE1 == '#')) {
			ret = '<';
		} else {
			ret = '>';
		}

		break;
	case '*':
	case '/':
		if ((sE1 == '*') || (sE1 == '/') || (sE1 == ')')) {
			ret = '>';
		} else {
			ret = '<';
		}

		break;
	case '(':
		if (sE1 == ')') {
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
			return ERR_PARA;
		} else {
			ret = '<';
		}

		break;
	case ')':
		switch (sE1) {
		case '(':
			ret = '=';
			break;
		case '#':
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
			return ERR_PARA;
		default:
			ret = '>';
		}

		break;
	case '#':
		switch (sE1) {
		case '#':
			ret = '=';
		case '(':
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
			return ERR_PARA;
		default:
			ret = '>';
		}
	}

	return ret;
}

/* 判断 ch 是否为运算符 */
Status IsOper(SElemType ch)
{
	switch (ch) {
	case '+':
	case '-':
	case '*':
	case '/':
	case '(':
	case ')':
	case '#':
		return TRUE;
	default:
		return FALSE;
	}
}

/* 通过操作符 oper 计算 元素 sE1 与 sE2 */
SElemType CaculateAction(SElemType sE1, SElemType sE2, SElemType oper)
{
	SElemType ret = 0;
	switch (oper) {
	case '+':
		ret = sE1 + sE2;
		break;
	case '-':
		ret = sE1 - sE2;
		break;
	case '*':
		ret = sE1 * sE2;
		break;
	case '/':
		if (sE2 == 0) {
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
			return ERR_PARA;
		} else {
			ret = sE1 / sE2;
		}
	}

	return ret;
}


/* 算法 3.4, 算术表达式求值的算符优先算法。设 OPTR 和 OPND 分别为运算符栈和运算数栈
   输入数值需要在 0 ~ 9 之间, 原因为运算数仅能保存于单个字符中 */
SElemType CaculateExpression(void)
{
	SqStack OPTR = { 0 }, OPND = { 0 };
	InitStack(&OPTR);
	InitStack(&OPND);
	Push(&OPTR, '#');
	SElemType topSE = 0;
	GetTop(OPTR, &topSE);
	SElemType sE1 = 0, sE2 = 0, oper = 0;
	SElemType ch = getchar();
	while ((ch != '#') || (topSE != '#')) {
		if (IsOper(ch)) {
			switch (OperPriority(topSE, ch)) {
			case '<':
				Push(&OPTR, ch);
				ch = getchar();
				break;
			case '=':
				Pop(&OPTR, &topSE);
				ch = getchar();
				break;
			case '>':
				Pop(&OPTR, &oper);
				Pop(&OPND, &sE2);
				Pop(&OPND, &sE1);
				Push(&OPND, CaculateAction(sE1, sE2, oper));
				break;
			}
		} else if ((ch >= '0') && (ch <= '9')) {
			/* 将 ASCII 码转换为数字, 数字 0 ~ 9 的 ASCII 码为 48 ~ 57 */
			ch -= 48;
			Push(&OPND, ch);
			ch = getchar();
		} else {
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
			return ERR_PARA;
		}

		GetTop(OPTR, &topSE);
	}

	GetTop(OPND, &topSE);

	return topSE;
}

/* 算法 3.4<2>, 算术表达式求值的算符优先算法。设 OPTR 和 OPND 分别为运算符栈和运算数栈
   对算法 3.4 的优化,解除输入限制, 输入负数时使用 0 - n 的方式输入 */
SElemType CaculateExpression2(void)
{
	SqStack OPTR = { 0 }, OPND = { 0 };
	InitStack(&OPTR);
	InitStack(&OPND);
	Push(&OPTR, '#');
	SElemType topSE = 0;
	GetTop(OPTR, &topSE);
	SElemType sE1 = 0, sE2 = 0, oper = 0;
	char ch = getchar();
	char numStr[6] = { 0 };
	while ((ch != '#') || (topSE != '#')) {
		if (IsOper(ch)) {
			switch (OperPriority(topSE, ch)) {
			case '<':
				Push(&OPTR, ch);
				ch = getchar();
				break;
			case '=':
				Pop(&OPTR, &topSE);
				ch = getchar();
				break;
			case '>':
				Pop(&OPTR, &oper);
				Pop(&OPND, &sE2);
				Pop(&OPND, &sE1);
				Push(&OPND, CaculateAction(sE1, sE2, oper));
				break;
			}
		} else if ((ch >= '0') && (ch <= '9')) {
			/* 将 ASCII 码转换为数字, 数字 0 ~ 9 的 ASCII 码为 48 ~ 57 */
			int i;
			for (i = 0; (ch >= '0') && (ch <= '9'); ++i) {
				numStr[i] = ch;
				ch = getchar();
			}

			numStr[i] = 0;
			int num = atoi(numStr);
			Push(&OPND, num);
		} else {
			printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_PARA);
			return ERR_PARA;
		}

		GetTop(OPTR, &topSE);
	}

	GetTop(OPND, &topSE);

	return topSE;
}

8) main.c

/* 入口程序源文件 */

#include "status.h"
#include "sqStack.h"
#include "algorithm.h"
#include "auxiliary.h"
#include <stdio.h>
#include <string.h>

int main(void)
{
	/* 测试基本功能 */
	SqStack S;
	int ret = InitStack(&S);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
		return ret;
	}

	for (int i = 0; i < 12; ++i) {
		Push(&S, i + 1);
	}

	StackTraverse(S, Print);
	printf("\n");

	SElemType e;
	ret = Pop(&S, &e);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
		return ret;
	}

	printf("The element of the top of the stack: %d\n", e);

	printf("The stack is %s\n", (StackEmpty(S) == TRUE) ? "Empty" : "Not Empty");

	ret = GetTop(S, &e);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
	}

	printf("The element of the top of the stack: %d\n", e);
	printf("The length of the stack is: %d\n", StackLength(S));
	ClearStack(&S);
	ret = GetTop(S, &e);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
	}

	ret = Pop(&S, &e);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
	}

	printf("The stack is %s\n", (StackEmpty(S) == TRUE) ? "Empty" : "Not Empty");

	/* 算法 3.1 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 */
	printf("Please input a positive number: ");
	unsigned int num;
	scanf_s("%u", &num);
	printf("The octal of the positive decimal number of %u is: ", num);
	Conversion(num);
	putchar('\n');

	/* 算法 3.1<2>, 对于输入的任意一个非负 10 进制整数,打印输出与其等值的 16 进制数 */
	printf("The hexadecimal of the positive decimal number of %u is: ", num); \
	TransOctalToHexa(num);
	putchar('\n');
	getchar();

	/* 对于输入的任意一个字符串,检验括号 ()、[] 是否配对 */
	char str[80] = { 0 };
	printf("Please input a string to check if the string is match: ");
	if (gets_s(str, sizeof(str)) == NULL) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY);
		return ERR_MEMORY;
	}

	ret = BracketMatchCheck(str, (int)strlen(str));
	if (ret == TRUE) {
		printf("The string is match\n");
	}
	else {
		printf("The string is not match\n");
	}

	/* 算法 3.2, 利用字符栈 S,从终端接收一行并送至调用过程的数据区 */
	printf("Please input a string:\n");
	ret = LineEdit();
	if (ret != TRUE) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
	}

	putchar('\n');
	getchar();

	/* 算法 3.4<2>, 算术表达式求值的算符优先算法。设 OPTR 和 OPND 分别为运算符栈和运算数栈
	   对算法 3.4 的优化,解除输入限制 */
	printf("Please input the arithmetic expression: ");
	ret = CaculateExpression2();
	printf("ret = %d\n", ret);

	DestroyStack(&S);

	return 0;
}

2.  输出示例:

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

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

相关文章

Python Opencv实践 - Canny边缘检测

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_GRAYSCALE) print(img.shape)#图像Canny边缘检测 #cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradien…

【第1章 数据结构概述】

目录 一. 基本概念 1. 数据、数据元素、数据对象 2. 数据结构 二. 数据结构的分类 1. 数据的逻辑结构可分为两大类&#xff1a;a. 线性结构&#xff1b;b. 非线性结构 2. 数据的存储结构取决于四种基本的存储方法&#xff1a;顺序存储、链接存储、索引存储、散列存储 3. …

【Unity】终极移动指南-注解【理解移动到抓钩,再到贪吃蛇的实现】

文章目录 【Unity】终极移动指南-注解&#xff08;从移动、抓钩到贪吃蛇&#xff09;观前提醒链接地址&#xff1a; 内容一、 transform移动操作【1】transform.position变换位置【2】transform.Translate平移【3】transform.position 类似平移的操作【4】定向矢量【5】停在指定…

教你快速记单词。一套高效的单词记忆法,背单词技巧 英语没有一个单词需要死记硬背的,5天能不能记住1万个单词 CrazyEnglish视频学习

就是这些辅音是可以互换的&#xff0c;之后我们就是换元音来组成新的单词 整个欧洲基本说的都是方言&#xff0c;他们很多真的就是发音和书写在变 这张图片超级重要 其实跟我们小时候学的那个拼音的那个背记排序好像是一样的 &#xff08;看到这个视频的后面&#xff0c;你就…

Linux操作系统中特定软件的安装

Linux中特定软件的安装 1、yum仓库2、在Linux中安装JDK3、在Linux中安装MySQL4、VMware的安装5、在VMware中安装CentOS6、克隆虚拟机 1、yum仓库 yum install -y 安装包的名字 更换yum的base源&#xff1a; /etc/yum.repos.d/CentOS-Base.repo 1、需要把原先的数据源做一个备…

算法题打卡day45-背包问题 | 70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数

70. 爬楼梯 - 力扣&#xff08;LeetCode&#xff09; 状态&#xff1a;查看思路后AC。 除了常规的可以爬一或二级台阶&#xff0c;当题目稍微修改一下&#xff0c;变成可以爬m级台阶&#xff0c;之前的DP思路就有局限&#xff08;dp[i] dp[i-1] dp[i-2&#xff09;&#xff0…

SpringAOP详解(下)

proxyFactory代理对象创建方式和代理对象调用方法过程&#xff1a; springaop创建动态代理对象和代理对象调用方法过程&#xff1a; 一、TargetSource的使用 Lazy注解&#xff0c;当加在属性上时&#xff0c;会产生一个代理对象赋值给这个属性&#xff0c;产生代理对象的代码为…

《向量数据库指南》——大模型时代向量数据库是刚需吗?

目录 从实际应用的角度来看 从技术发展的角度来看 如果你问我,我会毫不犹豫地回答:“是的,向量数据库是刚需。”为什么?听我慢慢给你解释。 首先,我们要理解什么是向量数据库。向量数据库是一种专门用于存储和查询向量数据的数据库。这些向量数据可以是文本、图像、音频…

基础数据结构:数组介绍

程序设计 数据结构算法 基本概念和术语 说到数据结构是什么&#xff0c;我们得先来谈谈什么叫数据。 正所谓"巧妇难为无米之炊’&#xff0c;再强大的计算机&#xff0c;也是要有"米’下锅才可以的&#xff0c;否则就是一堆破铜烂铁 这个"米"就是数据。…

【进程间通信】信号

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…

vsftpd使用遇到的问题

1.正常创建 安装到配置 yum install -y vsftpd systemctl start vsftpd useradd -d /home/ftpuser ftpuer passwd ftpuser vim /etc/vsftpd/vsftpd.conf i chroot_local_userYES allow_writeable_chrootYES chroot_list_enableYES chroot_list_file/etc/vsftpd/chroot_list2.连…

【计算机网络】序列化与反序列化

文章目录 1. 如何处理结构化数据&#xff1f;序列化 与 反序列化 2. 实现网络版计算器1. Tcp 套接字的封装——sock.hpp创建套接字——Socket绑定——Bind将套接字设置为监听状态——Listen获取连接——Accept发起连接——Connect 2. 服务器的实现 ——TcpServer.hpp初始化启动…

UDP 多播(组播)

前言&#xff08;了解分类的IP地址&#xff09; 1.组播&#xff08;多播&#xff09; 单播地址标识单个IP接口&#xff0c;广播地址标识某个子网的所有IP接口&#xff0c;多播地址标识一组IP接口。单播和广播是寻址方案的两个极端&#xff08;要么单个要么全部&#xff09;&am…

商城系统以拼团、砍价、分销为场景的用户增长,裂变和转化才是关键

其实&#xff0c;用户增长是一个非常大的话题。 用户增长不再是传统互联网意义上&#xff0c;一味地追求用户数量上的增长。用户增长是不断的提出增长假设&#xff0c;通过做实验与数据分析&#xff0c;验证假设的正确性&#xff0c;以此循环往复&#xff0c;反复迭代&#xf…

使用智能电磁流量计的时候有哪些方面要注意的?

在各大工业行业领域&#xff0c;流量计量的技术含量和多元性非常高。科学研究它们对提升产品质量、减少企业经营成本、环保节能和处理生态环境保护具有十分重要的意义。智能电磁流量计具备无摩擦阻力、没压力的优势&#xff0c;充足降低了管道里的摩擦阻力&#xff0c;合乎节能…

【微服务部署】02-配置管理

文章目录 1.ConfigMap1.1 创建ConfigMap方式1.2 使用ConfigMap的方式1.3 ConfigMap使用要点建议 2 分布式配置中心解决方案2.1 什么时候选择配置中心2.2 Apollo配置中心系统的能力2.2.1 Apollo创建配置项目2.2.2 项目使用2.2.3 K8s中使用Apollo 1.ConfigMap ConfigMap是K8s提供…

Yolov8-pose关键点检测:模型轻量化创新 | DCNV3结合c2f | CVPR2023

💡💡💡本文解决什么问题:模型轻量化创新引入DCNV3 DCNV3| GFLOPs从9.6降低至8.6,参数量从6482kb降低至5970kb, mAP50从0.921提升至0.926 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_63774211/category_12398833.html ✨✨✨手把手教你从数据标记到…

Java 集合框架1

一、集合框架 1.概念 二、Collection接口 Collection接口之下有两个子接口:List接口/Set接口 List接口是用来处理有序的单列数据&#xff0c;可以有重复的元素。 Set接口是用来处理无序的单列数据&#xff0c;没有重复的元素,重复的元素算一个 三、List接口 …

Redis 7 第三讲 数据类型 进阶篇

⑥ *位图 bitmap 1. 理论 由0和1 状态表现的二进制位的bit 数组。 说明:用String 类型作为底层数据结构实现的一种统计二值状态的数据类型 位图本质是数组,它是基于String 数据类型的按位操作。该数组由多个二进制位组成,每个二进制位都对应一个偏…

DC/DC开关电源学习笔记(一)开关电源技术概述

&#xff08;一&#xff09;开关电源技术概述 1.什么是开关电源&#xff1f;2.开关电源技术概述2.1 小型化、薄型化、轻量化、高频化2.2 高可靠性2.3 低噪声2.4 采用计算机辅助设计和控制 1.什么是开关电源&#xff1f; 开关模式电源&#xff08;Switch Mode Power Supply&…