动态顺序表——简单的增删查改

news2024/11/26 19:39:59

前言 :从这篇博客开始,我会进行数据结构(用C语言实现)有关内容的记录与分享。对于我们而言,数据结构的知识难度较大并且十分重要,希望我的分享给各位带来一些帮助。而今天要分享的就是数据结构中最简单的知识——顺序表的增删查改。

注:数据结构的学习中,画图是十分重要的,可以简化和加深对相关内容的理解,可能会花费较长时间,但是非常值得我们认真去做,这里分享一个有关数据结构的动图网站,希望也能对各位有所帮助:数据结构动图


目录

一、顺序表的简单介绍

(1) 概述

(2) 图示(动态顺序表)

二、动态顺序表实现简单的增删查改

(1) 大致框架的搭建

1. 工程的构建

2. 基本框架的搭建

3. 预备功能的实现——初始化,扩容,打印与销毁 

(2) 尾插尾删的实现

(3) 头插头删的实现

(4) 数据坐标的查找

(5) 定点位置的插入与删除

三:完整代码的展示

(1) Test.c

(2) SeqList.h

(3) SeqList.c



一、顺序表的简单介绍

(1) 概述

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。

顺序表一般分为静态顺序表(使用定长数组存储元素) 和 动态顺序表(使用动态开辟的数组存储),由于静态顺序表缺陷太多,所以在这里主要是对动态顺序表的介绍。

(2) 图示(动态顺序表)

注意
我们要明确,顺序表的本质还是数组,其增删查改就是在连续的数组上实现,不过就是数组数据的挪动,增加,删除,不用想的太过复杂。

二、动态顺序表实现简单的增删查改

(1) 大致框架的搭建

1. 工程的构建:

首先我们要建立一个简单的工程文件,包括三部分:

(1) Test.c——用于测试各个接口函数的源文件(自行控制接口函数的测试);

(2) SeqList.c——用于实现相关接口函数功能的源文件;

(3)SeqList.h——用于定义各个接口函数,顺序表结构以及各个库函数头文件的包含。

(说明:这样构建工程可以使得代码的可读性更强,逻辑更清晰,以后的文章大部分程序的基本构建都是如此,不会再重复说明)

2. 基本框架的搭建

(1) Test.c

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"
void Test1()//举个测试的例子
{
    SL a;
	SeqListInit(&a);

	SeqListPushBack(&a, 1);
	SeqListPushBack(&a, 2);
	SeqListPushBack(&a, 3);
	SeqListPushBack(&a, 4);
	SeqListPushBack(&a, 5);
	SeqListPrint(&a);

	SeqListPopBack(&a);
	SeqListPopBack(&a);
	SeqListPopBack(&a);
	SeqListPrint(&a);

	SeqListDestroy(&a);
}
void Test2()
{

}
void Test3()
{

}
//实现动态顺序表的增删查改(分三部分测试,方便反复测试,查找错误)
int main()
{
	//Test1();//尾插尾删
	
	//Test2();//头插头删

	Test3();//定点坐标的插入与删除
	return 0;
}

(2) SeqList.c

//各个接口函数的功能实现
void SeqListInit(SL* pa)//初始化
{

}

void CheckCapacity(SL* pa)//扩容
{

}

void SeqListPrint(SL* pa)//打印
{

}

void SeqListPushBack(SL* pa, SLDatatype x)//尾插
{

}
void SeqListPopBack(SL* pa)//尾删
{

}

void SeqListPushFront(SL* pa, SLDatatype x)//头插
{

}

void SeqListPopFront(SL* pa)//头删
{

}

int SeqListFind(SL* pa, SLDatatype x)//查找数据x,并返回其下标
{

}

void SeqListInsert(SL* pa, int pos, SLDatatype x)//在pos下标处插入x
{

}

void SeqListErase(SL* pa, int pos)//删除pos下标处数据
{

}

void SeqListDestroy(SL* pa)//销毁
{

}

(3) SeqList.h

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

typedef int SLDatatype;//将int类型重命名为SLDatatype(可以表示顺序表内数据的类型),方便更改

//顺序表结构的构建
typedef struct SeqList
{
	SLDatatype* a;//指向动态开辟的数组
	int sz;//数组中有效数据个数
	int capacity;//数组容量空间大小
} SL;

//接口函数的定义
void SeqListInit(SL* pa);//初始化
void CheckCapacity(SL* pa);//扩容
void SeqListPrint(SL* pa);//打印
void SeqListDestroy(SL* pa);//销毁

void SeqListPushBack(SL* pa, SLDatatype x);//尾插
void SeqListPopBack(SL* pa);//尾删
void SeqListPushFront(SL* pa, SLDatatype x);//头插
void SeqListPopFront(SL* pa);//头删

int SeqListFind(SL* pa, SLDatatype x);//查找数据x,并返回其下标
void SeqListInsert(SL* pa, int pos, SLDatatype x);//在pos下标处插入x
void SeqListErase(SL* pa, int pos);//删除pos下标处数据

3. 预备功能的实现——初始化,扩容,打印与销毁 

(1) 顺序表的初始化,打印与销毁

比较简单,不多多介绍:

void SeqListInit(SL* pa)//初始化
{
	assert(pa);
	pa->a = NULL;
	pa->capacity = pa->sz = 0;
}

void SeqListPrint(SL* pa)//打印———遍历数组即可
{
	int i = 0;
	for (i = 0;i < pa->sz;i++)
	{
		printf("%d ", pa->a[i]);
	}
	printf("\n");
}

void SeqListDestroy(SL* pa)//销毁顺序表
{
	assert(pa);
	free(pa->a);
	pa->a = NULL;
}

(2) 顺序表的扩容操作

由于是动态实现顺序表,所以空间是动态开辟出来的,进行数据插入时就会涉及到一个重要的步骤——空间不够,要进行扩容。

那就要使用我们在C语言学习中涉及的一个函数realloc,而扩容操作要思考全面,这里一共有三种情况,简单介绍一下:

1. 有效元素个数(sz)等于开辟空间大小(capacity)等于0,此时没有数据空间,需要开辟空间,而当realloc要扩容的空间为NULL时,其作用相当于malloc,即直接开辟设置的字节大小的空间即可。

2. 有效元素个数(sz)等于开辟空间大小(capacity)大于0,此时数据空间不够,需要进行扩容,直接使用realloc函数进行对应字节大小空间的扩容即可。

3. 有效元素个数(sz)不等于开辟空间大小(capacity)——此时不需要扩容,直接插入数据即可。

void CheckCapacity(SL* pa)//扩容
{
	if (pa->sz == pa->capacity)//前两种情况
	{
		int newcapacity = pa->capacity == 0 ? 4 : pa->capacity * 2;
		SLDatatype* tmp = realloc(pa->a, sizeof(SLDatatype) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		pa->a = tmp;
		pa->capacity = newcapacity;
	}
}

(2) 尾插尾删的实现

void SeqListPushBack(SL* pa, SLDatatype x)//尾插
{
	assert(pa);
	CheckCapacity(pa);//插入数据前要先判断是否需要扩容
	pa->a[pa->sz] = x;//最后一个有效元素之后插入x
	pa->sz++;
}

void SeqListPopBack(SL* pa)//尾删
{
	assert(pa);
	assert(pa->sz > 0);//删除数据的前提是顺序表中有有效元素
	pa->sz--;
}

这里是尾插尾删的简单实现,后面进一步实现一个接口函数后可以对其进行简化。


(3) 头插头删的实现

//头插与头删的原理都是对数据进行适当的挪动,要注意的是边界的控制,可以画图理解
void SeqListPushFront(SL* pa, SLDatatype x)//头插
{
	assert(pa);
	CheckCapacity(pa);
	int end = pa->sz - 1;
	while (end >= 0)
	{
		pa->a[end + 1] = pa->a[end];//挪动数据的过程
		end--;
	}
	pa->a[0] = x;
	pa->sz++;
}

void SeqListPopFront(SL* pa)//头删
{
	assert(pa);
	assert(pa->sz > 0);//无数据,不可删
	int begin = 0;
	while (begin < pa->sz - 1)
	{
		pa->a[begin] = pa->a[begin + 1];//挪动数据的过程
		begin++;
	}
	pa->sz--;
}

(4) 数据坐标的查找

//遍历数组,查找数据x,并返回其下标
int SeqListFind(SL* pa, SLDatatype x)
{
	assert(pa);
	int i = 0;
	for (i = 0;i < pa->sz;i++)
	{
		if (pa->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

(5) 定点位置的插入与删除

void SeqListInsert(SL* pa, int pos, SLDatatype x)//在pos下标处插入数据x
{
	assert(pa);
	CheckCapacity(pa);//扩容
	int i = 0;
	int end = pa->sz - 1;
	for (i = end;i >= pos;i--)//挪动数据的思想————前向后移
	{
		pa->a[i + 1] = pa->a[i];
	}
	pa->a[pos] = x;
	pa->sz++;
}

void SeqListErase(SL* pa,int pos)//删除pos下标处数据
{
	assert(pa);
	assert(pa->sz > 0);//判空
	int i = 0;
	for (i = pos;i < pa->sz - 1;i++)//挪动数据的思想————后向前移,覆盖pos位置的数据
	{
		pa->a[i] = pa->a[i + 1];
	}
	pa->sz--;
}

注意:这两个函数接口是顺序表中较为重要的两个,调用这两个函数接口可以解决顺序表的插入与删除。同时,用这两个函数接口可以对头插头删,尾插尾删进行简化:

void SeqListPushBack(SL* pa, SLDatatype x)//尾插
{
	SeqListInsert(pa, pa->sz, x);//调用SeqListInsert函数简化尾插,在最后一个元素后插入元素
}

void SeqListPopBack(SL* pa)//尾删
{
	SeqListErase(pa, pa->sz - 1);//调用SeqListErase函数简化尾删,删除最后一个元素
}

void SeqListPushFront(SL* pa, SLDatatype x)//头插
{
	SeqListInsert(pa, 0, x);//调用SeqListInsert函数简化头插,在第一个元素处插入元素
}

void SeqListPopFront(SL* pa)//头删
{
	SeqListErase(pa, 0);//调用SeqListErase函数简化头删,删除首位位置元素
}


三:完整代码的展示

(1) Test.c

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"

void Test1()//尾插尾删的测试
{
	SL a;
	SeqListInit(&a);

	SeqListPushBack(&a, 1);
	SeqListPushBack(&a, 2);
	SeqListPushBack(&a, 3);
	SeqListPushBack(&a, 4);
	SeqListPushBack(&a, 5);
	SeqListPrint(&a);

	SeqListPopBack(&a);
	SeqListPopBack(&a);
	SeqListPopBack(&a);
	SeqListPrint(&a);

	SeqListDestroy(&a);
}

void Test2()//头插头删的测试
{
	SL a;
	SeqListInit(&a);

	SeqListPushFront(&a, 1);
	SeqListPushFront(&a, 2);
	SeqListPushFront(&a, 3);
	SeqListPushFront(&a, 4);
	SeqListPushFront(&a, 5);
	SeqListPrint(&a);

	SeqListPopFront(&a);
	SeqListPopFront(&a);
	SeqListPrint(&a);

	SeqListDestroy(&a);
}

void Test3()//定点坐标的插入与删除的测试
{
	SL a;
	SeqListInit(&a);
	SeqListPushFront(&a, 1);
	SeqListPushFront(&a, 2);
	SeqListPushBack(&a, 3);
	SeqListPushBack(&a, 4);
	SeqListPrint(&a);
	
	int pos = SeqListFind(&a, 1);//找到原顺序表中是否有1,有则在其下标处插入5
	if (pos != -1)
	{
		SeqListInsert(&a, pos, 5);
	}
	SeqListPrint(&a);

	pos = SeqListFind(&a, 2);//找到原顺序表中是否有2,有则在其下标处插入6
	if (pos != -1)
	{
		SeqListInsert(&a, pos, 6);
	}
	SeqListPrint(&a);

	pos = SeqListFind(&a, 2);//找到原顺序表中是否有2,有则删除
	if (pos != -1)
	{
		SeqListErase(&a, pos);
	}
	SeqListPrint(&a);

	pos = SeqListFind(&a, 1);//找到原顺序表中是否有1,有则删除
	if (pos != -1)
	{
		SeqListErase(&a, pos);
	}
	SeqListPrint(&a);

	SeqListDestroy(&a);
}
//实现动态顺序表的增删查改(分三部分测试,方便反复测试,查找错误)
int main()
{
	//Test1();//尾插尾删
	
	//Test2();//头插头删

	Test3();//定点坐标的插入与删除
	return 0;
}

(2) SeqList.h

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

typedef int SLDatatype;//将int类型重命名为SLDatatype(可以表示顺序表内数据的类型),方便更改

//顺序表结构的构建
typedef struct SeqList
{
	SLDatatype* a;//指向动态开辟的数组
	int sz;//数组中有效数据个数
	int capacity;//数组容量空间大小
} SL;

void SeqListInit(SL* pa);//初始化
void CheckCapacity(SL* pa);//扩容
void SeqListPrint(SL* pa);//打印
void SeqListDestroy(SL* pa);//销毁

void SeqListPushBack(SL* pa, SLDatatype x);//尾插
void SeqListPopBack(SL* pa);//尾删

void SeqListPushFront(SL* pa, SLDatatype x);//头插
void SeqListPopFront(SL* pa);//头删

int SeqListFind(SL* pa, SLDatatype x);//查找数据x,并返回其下标
void SeqListInsert(SL* pa, int pos, SLDatatype x);//在pos下标处插入x
void SeqListErase(SL* pa, int pos);//删除pos下标处数据

(3) SeqList.c

#define _CRT_SECURE_NO_WARNINGS
#include "SeqList.h"

void SeqListInit(SL* pa)//初始化
{
	assert(pa);
	pa->a = NULL;
	pa->capacity = pa->sz = 0;
}

void SeqListPrint(SL* pa)//打印———遍历数组即可
{
	int i = 0;
	for (i = 0;i < pa->sz;i++)
	{
		printf("%d ", pa->a[i]);
	}
	printf("\n");
}

void CheckCapacity(SL* pa)//扩容
{
	if (pa->sz == pa->capacity)//前两种情况
	{
		int newcapacity = pa->capacity == 0 ? 4 : pa->capacity * 2;
		SLDatatype* tmp = realloc(pa->a, sizeof(SLDatatype) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		pa->a = tmp;
		pa->capacity = newcapacity;
	}
}

void SeqListPushBack(SL* pa, SLDatatype x)//尾插
{
	/*assert(pa);
	CheckCapacity(pa);
	pa->a[pa->sz] = x;
	pa->sz++;*/

	SeqListInsert(pa, pa->sz, x);//调用SeqListInsert函数简化尾插
}

void SeqListPopBack(SL* pa)//尾删
{
	/*assert(pa);
	assert(pa->sz > 0);
	pa->sz--;*/

	SeqListErase(pa, pa->sz - 1);//调用SeqListErase函数简化尾删
}

void SeqListPushFront(SL* pa, SLDatatype x)//头插
{
	/*assert(pa);
	CheckCapacity(pa);
	int end = pa->sz - 1;
	while (end >= 0)
	{
		pa->a[end + 1] = pa->a[end];
		end--;
	}
	pa->a[0] = x;
	pa->sz++;*/

	SeqListInsert(pa, 0, x);//调用SeqListInsert函数简化头插
}

void SeqListPopFront(SL* pa)//头删
{
	/*assert(pa);
	assert(pa->sz > 0);
	int begin = 0;
	while (begin < pa->sz - 1)
	{
		pa->a[begin] = pa->a[begin + 1];
		begin++;
	}
	pa->sz--;*/

	SeqListErase(pa, 0);//调用SeqListErase函数简化头删
}

int SeqListFind(SL* pa, SLDatatype x)//查找数据x,并返回其下标
{
	assert(pa);
	int i = 0;
	for (i = 0;i < pa->sz;i++)
	{
		if (pa->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

void SeqListInsert(SL* pa, int pos, SLDatatype x)//在pos下标处插入x
{
	assert(pa);
	CheckCapacity(pa);
	int i = 0;
	int end = pa->sz - 1;
	for (i = end;i >= pos;i--)//挪动数据的思想————前向后移
	{
		pa->a[i + 1] = pa->a[i];
	}
	pa->a[pos] = x;
	pa->sz++;
}

void SeqListErase(SL* pa,int pos)//删除pos下标处数据
{
	assert(pa);
	assert(pa->sz > 0);
	int i = 0;
	for (i = pos;i < pa->sz - 1;i++)//挪动数据的思想————后向前移,覆盖pos位置的数据
	{
		pa->a[i] = pa->a[i + 1];
	}
	pa->sz--;
}

void SeqListDestroy(SL* pa)//销毁顺序表
{
	assert(pa);
	free(pa->a);
	pa->a = NULL;
}

总结

这样,我对动态开辟的顺序表的介绍就结束了,涉及增删查改各个操作共十一个接口函数,大家如果不会的话,可以先参照起始的模板自己尝试进行代码书写,再看看各个接口函数是如何实现的,当然如有错误,还望各位不吝赐教。最后,希望我的总结理解可以给各位带来一定的帮助,谢谢完整看完我文章的每一位,再见。


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

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

相关文章

11.Java方法的综合练习题大全-双色球彩票系统,数字的加密和解密等试题

本篇文章是Java方法的专题练习,从第五题开始难度增大,涉及大厂真题,前四道题目是基础练习,友友们可有目的性的选择学习&#x1f618;&#x1f495; 文章目录前言一、数组的遍历1.注意点:输出语句的用法2.题目正解二、数组最大值三、判断是否存在四、复制数组五、案例一:卖飞机票…

【学习笔记之数据结构】二叉树(一)

二叉树的概念&#xff1a; 二叉树是一种树的度不大于2的树&#xff0c;也就是它的节点的度都是小于等于2的。二叉树的子树有左右之分&#xff0c;左右的次序不能颠倒&#xff0c;因此二叉树是一个有序树。任意的二叉树都由空树、只有根节点、只有左子树、只有右子树、左右子树均…

一个简单的自托管图片库HomeGallery

什么是 HomeGallery &#xff1f; HomeGallery 是一个自托管的开源 Web 图片库&#xff0c;用于浏览个人照片和视频&#xff0c;其中包括标记、对移动端友好和 AI 驱动的图像和面部发现功能。 HomeGallery 的独特功能是自动 相似图像/反向图像搜索功能 和 无数据库架构 &#x…

实验三、8人智力竞赛抢答电路设计

实验三 8人智力竞赛抢答电路设计 实验目的 设计一个能支持八路抢答的智力竞赛抢答器&#xff1b;主持人按下开始抢答的按键后&#xff0c;有短暂的报警声提示抢答人员抢答开始且指示灯亮表示抢答进行中&#xff1b;在开始抢答后数码管显8秒倒计时&#xff1b;有抢答人员按下抢…

Linux企业应用现状

一、Linux在服务器领域的发展 随着开源软件在世界范围内影响力日益增强&#xff0c;Linux服务器操作系统在整个服务器操作系统市场格局中占据了越来越多的市场份额&#xff0c;已经形成了大规模市场应用的局面。并且保持着快速的增长率。尤其在政府、金融、农业、交通、电信等国…

linux 网络编程socket

前言 socket&#xff08;套接字&#xff09;是linux下进程间通信的一种方式&#xff0c;通常使用C-S&#xff08;客户端-服务端&#xff09;的方式通信&#xff0c;它可以是同一主机下的不同进程间通信或者不同主机的进程通信。 socket是夹在应用层和TCP/UDP协议层间的软件抽象…

机器自动翻译古文拼音 - 将进酒拼音版本,译文拼音版本

写了一个程序&#xff0c;用来给佛经和古诗加上拼音&#xff0c;并处理多音字和排版&#xff0c;顺便加上翻译。 定期翻译一些&#xff0c;给老人和小孩子用。 将进酒 君不见&#xff0c;黄河之水天上来&#xff0c;奔流到海不复回。 君不见&#xff0c;高堂明镜悲白发&…

Servlet介绍及其概念

Servlet介绍及其概念一、Web基础二、编写HTTP Server&#xff0c;打印Hello,World三、Servlet的出现1. 思考上述HTTP服务器的问题2. 实现代码重用&#xff0c;简化开发过程3. 实现最简单的Servlet4. 导入依赖5. pom.xml文件6. Servlet版本问题7. 整个Servlet工程结构四、运行Se…

Windows卸载与清除工具 “ Geek 与 CCleaner ”

前言 &#x1f4dc;“作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 目录 前言 一、Geek的简介 1、大概介绍 2、详细介绍 二、Geek的下载 1、…

千峰Ajax【fetch和promise】

promise基础 <script>// Promise构造函数var q new Promise(function (resolve, reject) {//异步setTimeout(function () {// 成功// resolve(["111", "222", "333"]);// 失败reject("error");}, 2000);});// q是promise对象q…

利用系统函数与堆栈快速定位app关键代码

string.trim 这个还是比较关键的&#xff0c;没准可以从这里得到加密方式&#xff0c;或者挖到sql注入&#xff0c;文件上传等漏洞。进一步利用可以打印堆栈来用 Java.perform(function(){function showStack(){console.log(Java.use("android.util.Log").getStack…

TCP/IP网络编程——基于 TCP 的服务端/客户端(下)

完整版文章请参考&#xff1a; TCP/IP网络编程完整版文章 文章目录第 5 章 基于 TCP 的服务端/客户端&#xff08;2&#xff09;5.1 回声客户端的完美实现5.1.1 回声服务器没有问题&#xff0c;只有回声客户端有问题&#xff1f;5.1.2 回声客户端问题的解决办法5.1.3 如果问题不…

chrome插件开发时使用import

问题描述 在进行chrome插件开发时&#xff0c;我们有时会希望把一些公共的方法包装成一个模块&#xff0c;例如发送网络请求的方法&#xff0c;然后在其他js文件中import然后调用&#xff0c;但是在实际操作时&#xff0c;遇到了这样的问题&#xff1a; 控制台报错cannot use …

Vistual Studio Code 安装与配置C/C++环境

1. 下载VScode 2. 安装cpptools工具 3. 下载MinGW 4. 配置环境变量 5. 使用简单的.cpp文件配置C环境 6. 运行 注&#xff1a;本文所有的地址配置要根据读者的实际情况来&#xff0c;不要照文章复制&#xff01;&#xff01;&#xff01; 下载VScode 下载链接&#xff1a;https…

浏览器调用本地DLL的方法

要在浏览器中调用本地DLL&#xff0c;常见的方法是使用插件。但是为了安全&#xff0c;现在有的浏览器对插件开发做了限制&#xff0c;不让插件调用外部DLL。比如说Chrome&#xff0c;为了调用外部的DLL&#xff0c;我们只能使用早期的chrome版本。 还有一种方法就是在电脑上安…

linux编辑器的使用(gcc,g++)

前言 gcc/g是一个编译器。 我们程序的翻译有四个步骤1.预处理(头文件展开&#xff0c;条件编译&#xff0c;宏替换&#xff0c;去注释)2.编译(c语言汇编语言)3.汇编(汇编->可重定位目标二进制文件&#xff0c;不可以被执行的&#xff0c;bin.obj)----只是把我们自己的代码进…

下载Windows ISO镜像的方法 (超详细 适合新手入门)

前言 &#x1f4dc;“作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 目录 前言 一、镜像介绍 1、大概介绍 2、详细介绍 二、下载Window…

Solon 1.12.4 发布

一个更现代感的 Java "生态型"应用开发框架&#xff1a;更快、更小、更自由。不是 Spring&#xff0c;没有 Servlet&#xff0c;也无关 JavaEE&#xff1b;新兴独立的开放生态 &#xff08;已有150来个生态插件&#xff09; 。主框架仅 0.1 MB。 相对于 Spring Boot…

JVM学习总结,全面介绍运行时数据区域、各类垃圾收集器的原理使用、内存分配回收策略

参考资料&#xff1a;《深入理解Java虚拟机》第三版 文章目录一&#xff0c;运行时数据区域&#xff08;基础重中之重&#xff09;二&#xff0c;垃圾收集器与内存分配策略1&#xff09;对象已死2&#xff09;再谈引用3&#xff09;对象回收4&#xff09;内存分代收集理论&…

【HBase入门】10. HBase高可用、HBase架构、常见问题汇总

HBase高可用 考虑关于HBase集群的一个问题&#xff0c;在当前的HBase集群中&#xff0c;只有一个Master&#xff0c;一旦Master出现故障&#xff0c;将会导致HBase不再可用。所以&#xff0c;在实际的生产环境中&#xff0c;是非常有必要搭建一个高可用的HBase集群的。 HBase…