[数据结构]二叉树的链式结构

news2025/7/19 16:50:37

作者: 华丞臧
专栏:【数据结构】
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。
推荐一款刷题网站 👉 LeetCode刷题网站 

目录

前言

一、二叉树的链式结构

二、二叉树链式结构的实现

2.1 前序遍历

2.2 中序遍历

2.3 后序遍历

2.4 层序遍历

2.5 二叉树节点个数

2.6 二叉树叶子节点个数

2.7 二叉树第k层节点个数 

2.8 二叉树的高度

2.9 二叉树查找值为x的节点 

2.10 通过前序遍历的数组构建二叉树

2.11 判断二叉树是否是完全二叉树

2.12 二叉树销毁

 三、完整代码及测试

3.1 BTree.h

3.2 BinaryTreeNode.c

3.3 test.c

3.4 测试



前言

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是 链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所 在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链。

一、二叉树的链式结构

//二叉链结构
typedef int BTDataType;
typedef struct BinaryTreeNode
{
 BTDataType data;
 struct BinaryTreeNode* left;
 struct BinaryTreeNode* right;
}BTNode;

 

 

 回顾二叉树的概念,二叉树是:

  1. 空树
  2. 非空树:根节点及其左右子树构成。
  3. 树的定义是递归式的。

二、二叉树链式结构的实现

 学习二叉树的结构,最简单的方式就是遍历。所谓遍历就是按照某种特定规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。 

2.1 前序遍历

前序遍历(Preorder Traversal 亦称先序遍历,先根遍历)——访问根结点的操作发生在遍历其左右子树之前

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	//assert(root);

	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%d ", root->data);         //先访问根结点
	BinaryTreePrevOrder(root->left);   //递归左子树
	BinaryTreePrevOrder(root->right);  //递归右子树

}

2.2 中序遍历

 中序遍历(Inorder Traversal,又称中根遍历)——访问根结点的操作发生在遍历其左右子树之中(间)

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	BinaryTreeInOrder(root->left);
	printf("%d ",root->data);
	BinaryTreeInOrder(root->right);
}

2.3 后序遍历

 后序遍历(Postorder Traversal,又称后根遍历)——访问根结点的操作发生在遍历其左右子树之后

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ",root->data);
}

2.4 层序遍历

 除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在 层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层 上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历

需要使用队列来实现层序遍历,先把根节点入队列,每访问队列首元素后再把其出队列,并且把该节点的左右节点入队列;一直循环知道队列为空结束

   队列代码👉队列代码

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue p;
	QueueInit(&p);

	QueuePush(&p, root);

	while (!QueueEmpty(&p))
	{
		root = QueueFront(&p);
		printf("%d ", root->data);

		QueuePop(&p);
		QueuePush(&p, root->left);
		QueuePush(&p, root->right);
	}
	printf("\n");
	QueueDestroy(&p);
}

2.5 二叉树节点个数

 二叉树的节点个数等于根节点左子树右子树的节点个数,而左右子树节点个数又是根节点左子树右子树。

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	
	return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;

    //改良
	//return root == NULL ? 0 : 
            TreeSize(root->left) + TreeSize(root->right) + 1;
}

2.6 二叉树叶子节点个数

 叶节点就是左右子树都为空树的节点,一棵树的叶子节点就等于左子树叶子节点加上右子树叶子节点

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}

	return BinaryTreeLeafSize(root->left) 
        + BinaryTreeLeafSize(root->right);
}

2.7 二叉树第k层节点个数 

转换成递归k-1。当递归到k=1时,此时节点就是第k层的节点

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
    assert(k > 0);

	if (root == NULL)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}


	return BinaryTreeLevelKSize(root->left,k-1)     
                + BinaryTreeLevelKSize(root->right, k - 1);
	
}

2.8 二叉树的高度

一颗二叉树的高度等于左右子树高度大的那个加一

//二叉树的高度
int BinaryTreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	int left = BinaryTreeHeight(root->left);
	int right = BinaryTreeHeight(root->right);

	return left > right ? left + 1 : right + 1;
}

2.9 二叉树查找值为x的节点 

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}

	if (root->data == x)
	{
		return root;
	}

	BTNode* retleft = BinaryTreeFind(root->left,x);
	BTNode* retright = BinaryTreeFind(root->right, x);

	if (retleft != NULL)
	{
		return retleft;
	}
	else if(retright != NULL)
	{
		return retright;
	}
	else
	{
		return NULL;
	}
}

2.10 通过前序遍历的数组构建二叉树

注意需要用一个指针来控制数组a的移动,这样可以实现依次读取数组a里面的值,指针可以在递归的时候改变变量的值。 

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
	if (a[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}
	
	BTNode* root= (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	root->data = a[*pi];
	(*pi)++;
	root->left = BinaryTreeCreate(a, pi);
	root->right = BinaryTreeCreate(a, pi);

	return root;
}

2.11 判断二叉树是否是完全二叉树

需要利用队列这个数据结构来实现。

与层序遍历类似,先把根节点入队列,每访问队列首元素后再把其出队列,并且把该节点的左右节点入队列,只不过当节点为NULL时也需要入队列;当首元素出队列为NULL指针时,需要判断之后是否还会出现不为NULL指针的节点,如果出现,则不是完全二叉树返回false;如果没出,则是完全二叉树返回true

   队列代码👉队列代码

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	Queue pq;
	QueueInit(&pq);
	int flag = 0;

	QueuePush(&pq,root);

	while (!QueueEmpty(&pq))
	{
		root = QueueFront(&pq);
		if (root == NULL)
		{
			flag = 1;
		}

		if (flag == 1 && root != NULL)
		{
			QueueDestroy(&pq);
			return false;
		}

		QueuePop(&pq);
		if (root != NULL)
			QueuePush(&pq, root->left);
		if (root != NULL)
			QueuePush(&pq, root->right);
	}

	QueueDestroy(&pq);
	return true;
}

2.12 二叉树销毁

销毁二叉树需要后序遍历,先访问根节点的左右子树再销毁根节点。

// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

 三、完整代码及测试

  全部代码👉队列+二叉树链式结构全部代码

3.1 BTree.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

BTNode* BuyNode(BTDataType x);

// 通过前序遍历的数组构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi);

// 二叉树销毁
void BinaryTreeDestory(BTNode* root);

// 二叉树节点个数
int BinaryTreeSize(BTNode* root);

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

//二叉树的高度
int BinaryTreeHeight(BTNode* root);

3.2 BinaryTreeNode.c

#include "BTree.h"
#include "Queue.h"

BTNode* BuyNode(BTDataType x)
{
	BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));
	if (tmp == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	tmp->data = x;
	tmp->left = NULL;
	tmp->right = NULL;
	return tmp;
}

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	//assert(root);

	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%d ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);

}

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	BinaryTreeInOrder(root->left);
	printf("%d ",root->data);
	BinaryTreeInOrder(root->right);
}


// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ",root->data);
}

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	
	return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;

	//return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}


// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	int count = BinaryTreeLeafSize(root->left) 
		+ BinaryTreeLeafSize(root->right);

	return count;
}


// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}

	return BinaryTreeLevelKSize(root->left,k-1) 
		+ BinaryTreeLevelKSize(root->right, k - 1);
	
}

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}

	if (root->data == x)
	{
		return root;
	}

	BTNode* retleft = BinaryTreeFind(root->left,x);
	BTNode* retright = BinaryTreeFind(root->right, x);

	if (retleft != NULL)
	{
		return retleft;
	}
	else if(retright != NULL)
	{
		return retright;
	}
	else
	{
		return NULL;
	}
}


// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	Queue pq;
	QueueInit(&pq);
	int flag = 0;

	QueuePush(&pq,root);

	while (!QueueEmpty(&pq))
	{
		root = QueueFront(&pq);
		if (root == NULL)
		{
			flag = 1;
		}

		if (flag == 1 && root != NULL)
		{
			QueueDestroy(&pq);
			return false;
		}

		QueuePop(&pq);
		if (root != NULL)
			QueuePush(&pq, root->left);
		if (root != NULL)
			QueuePush(&pq, root->right);
	}

	QueueDestroy(&pq);
	return true;
}


// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue p;
	QueueInit(&p);

	QueuePush(&p, root);

	while (!QueueEmpty(&p))
	{
		BTNode* front = QueueFront(&p);
		QueuePop(&p);
		printf("%d ", front->data);

		if(front->left != NULL)
			QueuePush(&p, front->left);
		if (front->right != NULL)
			QueuePush(&p, front->right);
	}
	printf("\n");
	QueueDestroy(&p);
}


// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
	if (a[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}
	
	BTNode* root= (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	root->data = a[*pi];
	(*pi)++;
	root->left = BinaryTreeCreate(a, pi);
	root->right = BinaryTreeCreate(a, pi);

	return root;
}

// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

//二叉树的高度
int BinaryTreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	int left = BinaryTreeHeight(root->left);
	int right = BinaryTreeHeight(root->right);

	return left > right ? left + 1 : right + 1;
}

3.3 test.c

#include "BTree.h"
#include "Queue.h"


BTNode* CreatBinaryTree()
{
	BTNode* n1 = BuyNode(1);
	BTNode* n2 = BuyNode(2);
	BTNode* n3 = BuyNode(3);
	BTNode* n4 = BuyNode(4);
	BTNode* n5 = BuyNode(5);
	BTNode* n6 = BuyNode(6);
	BTNode* n7 = BuyNode(7);

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = n7;
	n4->left = n5;
	n4->right = n6;

	/*n2->right = NULL;
	n3->right = NULL;
	n3->left = NULL;
	n5->right = NULL;
	n5->left = NULL;
	n6->right = NULL;
	n6->left = NULL;*/

	return n1;
}


int main()
{
	BTNode* root = CreatBinaryTree();
	//BTNode* root = NULL;
	printf("前序:");
	BinaryTreePrevOrder(root);
	printf("\n");

	printf("中序:");
	BinaryTreeInOrder(root);
	printf("\n");

	printf("后序:");
	BinaryTreePostOrder(root);
	printf("\n");


	printf("TreeSize = %d\n", BinaryTreeSize(root)); 

	printf("TreeLeafSize = %d\n", BinaryTreeLeafSize(root));

	printf("Level K Size = %d\n", BinaryTreeLevelKSize(root,1));

	printf("TreeHeight = %d\n", BinaryTreeHeight(root));


	BTNode* tmp =  BinaryTreeFind(root, 7);
	if (tmp == NULL)
	{
		perror("TreeFind = BinaryTreeFind fail");
		return -1;
	}
	printf("%d\n",tmp->data);

	printf("层序:");
	BinaryTreeLevelOrder(root);


	if (BinaryTreeComplete(root))
	{
		printf("BinaryTreeComplete:true\n");
	}
	else
	{
		printf("BinaryTreeComplete:false\n");
	}

	return 0;
}

3.4 测试

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

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

相关文章

10 种创新的智慧废弃物管理技术

美国人每年产生约 2.5 亿吨垃圾&#xff0c;其中只有 34% 被回收。尽管有环保意识&#xff0c;但其他几项统计资料&#xff0c;揭示了令人震惊的垃圾倾向。废弃物管理的复杂性以前从未如此极端&#xff0c;这就是为什么今天这个行业僱用了近 50 万人&#xff0c;他们承担着每天…

【序列比对】Needleman-Wunsch(全局)和Smith-Waterman(局部)算法py实现(多条回溯路径,三叉树思路,超详细注释)

Needleman-Wunsch和Smith-Waterman算法py实现&#xff08;多条回溯路径&#xff09; 话不多说&#xff0c;直接上结果图&#xff0c;多条回溯路径。 原理 代码详解&#xff08;以NW为例&#xff09; 导入包以及参数设置 import numpy as npsequence_1 "AACGTACTCAAG…

数据分析经典算法——红黑树

数据分析经典算法——红黑树红黑树的重要性红黑树的定义红黑树图解红黑树的重要性 红黑树的优势 红黑树能够以O(log2(N))的时间复杂度的时间复杂度进行搜索、插入、删除操作。 此外,任何不平衡都会在3次旋转之内解决。 这一点是AVL所不具备的。 而且实际应用中&#xff0c;很多…

JAVA concurrency -- AQS 源码详解

概述 AQS全称AbstractQueuedSynchronizer是 jdk 中一个非常重要的方法&#xff0c;这是一个 jdk 的同步器的实现&#xff0c;JUC 中的很多类例如ReentrantLock等的实现都依赖于 AQS。 CAS AQS 的同步实现方式依赖于 CAS&#xff0c;那么 CAS 究竟是什么呢&#xff1f; CAS全…

写了半个月近3万字,助你直接上手Flink,原来这就是流批一体的处理方式

Flink即刻出发1.1.Flink 数据流1.2.Flink 分层 API1.3.Flink流处理程序的一般流程1.4.搭建Flink工程1.4.1.创建Maven项目1.5.批处理的单词统计1.5.1.示例1.5.2.开发步骤1.5.3.参考代码1.6.流处理的单词统计1.6.1.示例1.6.2.开发步骤1.6.3. 参考代码&#xff1a;java语言实现1.6…

Vue学习

Vue学习(第一天) 1、Vue.js安装 1.创建vue项目 2.启动vue项目 3.vue的MVVM 2、vue学习-1 1.vue cli 1.什么是vue cli 2.vue cli使用前提-Node 3.vue cli使用前提-Webpack 4.vue cli的使用 5.认识vue cli3 6.目录结构 7.vue ui 项目管理工具 2.什么是路由 1.前端阶段 3.url和hi…

C++STL——string类与模拟实现

STL容器——string类什么是STLstring类字符串的标准什么是stringstring常用接口介绍string的初始化比较大小与赋值容量对象的修改访问及遍历操作string中的swap与C库中的swap的区别非成员函数string类的模拟实现深浅拷贝与现代写法什么是STL STL(standard template libaray-标…

WRFV3.8.1编译报错,无法显示exe文件

问题报错&#xff1a;在WRF中遇到了一个可能和ubuntu系统有关的报错&#xff0c;主要表现为random seed过小&#xff0c;找不到&#xff0c;无法进行compile&#xff0c;导致compile em_real后无法生成4个*.exe文件。第一个报错出现位置为&#xff1a;。附件为compile.log。 图…

【树莓派不吃灰】命令篇④ Linux 常用命令学习

目录1. 常用命令1.1 操作文件及目录1.2 系统常用命令1.3 压缩解压缩1.4 linux系统常用快捷键及符号命令2. Linux 命令大全❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-11-18 ❤️❤️ 本篇更新记录 2022-11-18 ❤️&#x…

YOLO系列改进之四十四——融入适配GPU的轻量级 G-GhostNet

文章目录前言一、解决问题二、基本原理三、​添加方法总结前言 作为当前先进的深度学习目标检测算法YOLOv7&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系列文章…

Adafruit_GFX matrix ws2812像素屏库使用教程AWTRIX2.0像素时钟

AWTRIX2.0像素时钟很炫酷但必须要与服务器配合使用。这个库可以做自己的点阵时钟离线版。想怎么玩就怎么玩不受服务器牵绊。 第一步&#xff1a;下载mixy库然后倒入&#xff0c;必须有以下库文件&#xff1a; Adafruit_GFX FastLED FastLED_NeoMatrix TomThumb #include <Li…

Seata 1.5.2 源码学习(Client端)

在上一篇中通过阅读Seata服务端的代码&#xff0c;我们了解到TC是如何处理来自客户端的请求的&#xff0c;今天这一篇一起来了解一下客户端是如何处理TC发过来的请求的。要想搞清楚这一点&#xff0c;还得从GlobalTransactionScanner说起。 启动的时候&#xff0c;会调用Global…

【计算机毕业设计】新冠疫情隔离人员信息管理系统+vue源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 网络的广泛应用给生活带来了十分的便利。所以把基于小程序的社区疫情防控管理与现在网络相结合&#xff0c;利用ssm框架技术建设基于小程序的社区疫情防控系统&#xff0c;实现基于小程序的社区疫情防控的信息…

双线路捆绑

双线路捆绑是在服务器上接入两条上网线路并行使用 以达到提高链路上下行带宽&#xff08;即上传和下载速度&#xff09;的目的 默认情况下双线路捆绑采用负载均衡模式&#xff0c;并可更改为互为备份模式。 在负载均衡模式下&#xff0c;双线路的使用是基于会话的&#xff0…

已经有 MESI 协议,为什么还需要 volatile 关键字?

本文已收录到 GitHub AndroidFamily&#xff0c;有 Android 进阶知识体系&#xff0c;欢迎 Star。技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好&#xff0c;我是小彭。 在上一篇文章里&#xff0c;我们聊到了 CPU 的缓存一致性问…

树莓派使用docker搭建owncloud私有云--外挂硬盘

一&#xff0e;安装docker 1. 一键脚本&#xff1a; sudo curl -sSL https://get.docker.com | sh2. 查看docker是否安装成功 docker -v出现版本号即为成功 二&#xff0e;每次开机自动挂载硬盘到树莓派 sudo nano /etc/fstab在最后一行加入挂载信息 /dev/sda1 /home/pi/…

[附源码]java毕业设计农村政务管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]SSM计算机毕业设计智慧农业销售平台JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

多进程编程 VS 多线程编程

目录 一、进程 & 线程 二、进程与线程的优劣势 三、在什么场景下需要使用多进程编程&#xff1f; 进程也可以称为是“任务”。操作系统要想执行一个具体的“动作”&#xff0c;就需要创建出一个对应的进程。 一个程序在没有运行的时候&#xff0c;它仅仅是一个“可执行…

RHCE学习 --- 第六次作业

RHCE学习 — 第六次作业 首先要先装DNS服务器需要的包 [rootlocalhost ~]# yum install bind -y然后开始配置DNS服务 配置文件位置在/etc/named.conf下&#xff0c;建议先备份 注&#xff1a;备份的时候要cp -a&#xff0c;否则所属组会变&#xff0c;导致文件不可用 然后编辑…