C语言二叉树和堆(个人笔记)

二叉树和堆

    • 二叉树
      • 1二叉树的概念和结构
        • 1.1特殊的二叉树
        • 1.2二叉树的性质(规定根节点的层数为1)
        • 1.3二叉树的存储结构
      • 2.二叉树的顺序结构和实现
        • 2.1二叉树的顺序结构
        • 2.2堆的概念和结构
        • 2.3堆的实现
        • 2.4堆的应用
          • 2.4.1堆排序
        • 2.5TOP-K问题
      • 3.二叉树的遍历
      • 4.二叉树的节点个数以及高度等
      • 5.笔试题

二叉树

1二叉树的概念和结构

一颗二叉树是节点的一个有限集合:

  1. 为空
  2. 由一个根节点加上两颗别称为左子树和右子树的二叉树组成

在这里插入图片描述

1.1特殊的二叉树
  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。 节点总数:2^k-1
  2. 完全二叉树:就是满二叉树的最后一层节点是不完全的,但视觉上看从左到右是不间断的。
1.2二叉树的性质(规定根节点的层数为1)
  1. 一颗非空二叉树的第i层上最多有2^(i-1)个节点
  2. 深度为h的二叉树最大节点数是2^h-1
  3. 对于任何一颗树,如果度为0其叶子节点的个数为n0,度为2的分支节点个数为n2,则有n0=n2+1
  4. 具有n个节点的满二叉树的深度,h=log2(n+1)
  5. 有n个节点的完全二叉树,按照从上至下从左到右的数组顺序对所有节点从0开始编号,则对于序号为i的节点有:
    1.若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点,则无双亲节点
    2.若2i+1<n,左孩子序号:2i+1,2i+1>=n则无左孩子
    3.若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子
1.3二叉树的存储结构

1.顺序存储
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费(如果说不是完全二叉树,但数组上要留空间给那些截断的地方)。而现实中使用中只有堆才会使用数组来存储。
二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

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

2.二叉树的顺序结构和实现

2.1二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

2.2堆的概念和结构

根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆的性质:
1.堆中某个节点的值总是不大于或不小于其父节点的值(不大于就是小堆,不小于就是大堆)
2.堆总是一棵完全二叉树。

2.3堆的实现
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int HPDataType;
typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;void HeapInit(HP* php)
{assert(php);php->a = NULL;php->capacity = 0;php->size = 0;
}void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = 0;php->capacity = 0;
}void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[parent] > a[child]){Swap(&a[parent], &a[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void AdjustDown(HPDataType* a,int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] > a[child + 1]){child = child + 1;}if (a[parent] > a[child]){Swap(&a[parent], &a[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}bool HeapEmpty(HP* php)
{assert(php);if (php->size == 0){return true;}else{return false;}
}void HeapPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newCapacity = php->capacity = 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newCapacity);if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity = newCapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);
}HPDataType HeapTop(HP* php)
{assert(php);assert(!HeapEmpty(php));return php->a[0];
}int HeapSize(HP* php)
{assert(php);return php->size;
}
2.4堆的应用
2.4.1堆排序

利用堆的思想进行排序,就两步:

  1. 建堆
    升序:建大堆
    降序:建小堆
    2.利用堆删除思想来进行排序
    建堆和堆删除中都用到了向下调整
void HeapSort(int* a, int n)
{// 升序 -- 建大堆// 降序 -- 建小堆// 建堆--向上调整建堆for (int i = 1; i < n; i++){AdjustUp(a, i);}// 建堆--向下调整建堆 --O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);// 再调整,选出次小的数AdjustDown(a, end, 0);--end;}
}int main()
{int a[] = { 7,8,3,5,1,9,5,4 };HeapSort(a, sizeof(a) / sizeof(int));return 0;
}
2.5TOP-K问题

即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
解决思路:

  1. 用数据集合中前K个元素来建堆
    前k个最大的元素,则建小堆
    前k个最小的元素,则建大堆
  2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。
void CreateNDate()
{//造数据int n = 1000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (size_t i = 0;i < n;i++){int x = rand() % 1000000;fprintf(fin, "%d\n", x);}fclose(fin);
}void PrintTopK(int k)
{const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fout fail");return;}int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc fail");return;}for (int i = 0;i < k;i++){fscanf(fout, "%d", &kminheap[i]);}//建小堆for (int i = (k - 1 - 1) / 2;i >= 0;i--){AdjustDown(kminheap, k, i);}int val = 0;while (!feof(fout)){fscanf(fout, "%d", &val);if (val > kminheap[0]){kminheap[0] = val;AdjustDown(kminheap, k, 0);}}for (int i = 0;i < k;i++){printf("%d ", kminheap[i]);}printf("\n");
}

3.二叉树的遍历

二叉树遍历是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。

  1. 前序遍历(根左子树右子树)
  2. 中序遍历(左子树根右子树)
  3. 后序遍历(左子树右子树根)
  4. 层序遍历(从根节点开始从左往右,从上到下,依次访问)
// 二叉树前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}
// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}PreOrder(root->left);printf("%d ", root->data);PreOrder(root->right);
}
// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}PreOrder(root->left);PreOrder(root->right);printf("%d ", root->data);
}//二叉树层序遍历(上一层出时带下一层进队列)
void LevelOrder(BTNode* root)
{Queue q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);printf("%d ", front->data);if (root->left){QueuePush(&q, root->left);}if (root->right){QueuePush(&q, root->right);}}printf("\n");QueueDestroy(&q);
}

4.二叉树的节点个数以及高度等

// 二叉树节点个数(左子树的节点个数加右子树的节点个数)
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 二叉树叶子节点个数(左子树的叶子节点个数加右子树叶子节点个数)
int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right = NULL){return 1;}return BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
//二叉树的高度(左子树的高度跟右子树高度比较)
int BTreeHeight(BTNode* root)
{if (root == NULL){return 0;}int LeftHeight = BTreeHeight(root->left);int RightHeight = BTreeHeight(root->right);return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
}// 二叉树第k层节点个数(左子树第k减一层的节点个数+右子树第k减一层的节点个数,返回条件k=1)
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) + BinaryTreeLeafSize(root->right,k-1);
}
// 二叉树查找值为x的节点(左子树找x,找到返回,右子树找x,找到返回,切记层层往回返)
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->val == x){return root;}BTNode* ret1=BinaryTreeFind(root->left, x);if (ret1){return ret1;}BTNode* ret2=BinaryTreeFind(root->right, x);if (ret2){return ret2;}return NULL;
}// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{if (a[*pi] == '#'){(*pi)++;return NULL;}BTNode* root = BuyNode(a[*pi]);(*pi)++;root->left = BinaryTreeCreate(a, n, pi);root->right= BinaryTreeCreate(a, n, pi);return root;
}
// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{if (root == NULL){return;}BinaryTreeDestory(root->left);BinaryTreeDestory(root->right);free(root);
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front == NULL){break;}QueuePush(&q, front->left);QueuePush(&q, front->right);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front){QueueDestroy(&q);return false;}}QueueDestroy(&q);return true;
}

5.笔试题

单值二叉树
在这里插入图片描述

//返回条件:遇到NULL返回true,根的左子树与根不同返回false,根的右子树与根不同返回false,相同什么都决定不了。
//左子树和右子树都相同才为真
bool isUnivalTree(struct TreeNode* root)
{if(root==NULL){return true;}if(root->left && root->left->val!=root->val){return false;}if(root->right && root->right->val!=root->val){return false;}return isUnivalTree(root->left) && isUnivalTree(root->right);
}

相同的树
在这里插入图片描述

//结束条件:两边都为空则true,一边为空一边不为空则false,值不同返回false
//左子树右子树都相等才行
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{if(p==NULL&&q==NULL){return true;}if(p==NULL||q==NULL){return false;}if(p->val!=q->val){return false;}return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}

对称二叉树
在这里插入图片描述

//相同的树小进阶题
bool _isSymmetric(struct TreeNode* l,struct TreeNode* r)
{if(l==NULL&&r==NULL){return true;}if(l==NULL||r==NULL){return false;}if(l->val!=r->val){return false;}return _isSymmetric(l->left,r->right)&&_isSymmetric(l->right,r->left);
}bool isSymmetric(struct TreeNode* root)
{return _isSymmetric(root->left,root->right);
}

二叉树的前序遍历
在这里插入图片描述

//这道题的意思是让你返回一个前序遍历塞进去的数组,*returnSize是输出型参数,是让你自己去计算值,然后再赋给它,下标i一定要传地址,如果不这样每一层递归都是一个新i,++就没有了意义
int _returnSize(struct TreeNode* root)
{if(root==NULL){return 0;}return _returnSize(root->left)+_returnSize(root->right)+1;
}void _preorderTraversal(struct TreeNode* root,int* a,int* pi)
{if(root==NULL){return;}a[(*pi)++]=root->val;_preorderTraversal(root->left,a,pi);_preorderTraversal(root->right,a,pi);
}int* preorderTraversal(struct TreeNode* root, int* returnSize)
{*returnSize=_returnSize(root);int* a=(int*)malloc(*returnSize*sizeof(int));int i=0;_preorderTraversal(root,a,&i);return a;
}

二叉树中序遍历

在这里插入图片描述

//代码与上题基本一致
int _returnSize(struct TreeNode* root)
{if(root==NULL){return 0;}return _returnSize(root->left)+_returnSize(root->right)+1;
}void _inorderTraversal(struct TreeNode*root,int* a,int* pi)
{if(root==NULL){return;}_inorderTraversal(root->left,a,pi);a[(*pi)++]=root->val;_inorderTraversal(root->right,a,pi);
}int* inorderTraversal(struct TreeNode* root, int* returnSize)
{*returnSize=_returnSize(root);int* a=(int*)malloc(sizeof(int)*(*returnSize));int i=0;_inorderTraversal(root,a,&i);return a;
}

二叉树后序遍历
在这里插入图片描述

//与上题基本一致
int _returnSize(struct TreeNode* root)
{if(root==NULL){return 0;}return _returnSize(root->left)+_returnSize(root->right)+1;
}void _postorderTraversal(struct TreeNode*root,int* a,int* pi)
{if(root==NULL){return;}_postorderTraversal(root->left,a,pi);_postorderTraversal(root->right,a,pi);a[(*pi)++]=root->val;
}int* postorderTraversal(struct TreeNode* root, int* returnSize)
{*returnSize=_returnSize(root);int* a=(int*)malloc(sizeof(int)*(*returnSize));int i=0;_postorderTraversal(root,a,&i);return a;
}

另一颗树的子树
在这里插入图片描述

//对比相同的树的变型题,思路:每一颗不为空的节点都可以认为子树的根,返回false
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{if(p==NULL&&q==NULL){return true;}if(p==NULL||q==NULL){return false;}if(p->val!=q->val){return false;}return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{if(root==NULL){return false;}if(isSameTree(root,subRoot)){return true;}return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}

二叉树的遍历
在这里插入图片描述

//除了创建树这个函数之外,其他的就是基操,创建树可以递归创建!!!
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
} BTNode;BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");return NULL;}node->data = x;node->left = NULL;node->right = NULL;return node;
}BTNode* CreateTree(char* a, int* pi)
{if(a[*pi]=='#'){(*pi)++;return NULL;}BTNode* root=BuyNode(a[*pi]);(*pi)++;root->left=CreateTree(a,pi);root->right=CreateTree(a,pi);return root;
}void InOrder(BTNode* root)
{if (root == NULL){return;}InOrder(root->left);printf("%c ", root->data);InOrder(root->right);
}int main()
{char arr[100] = { 0 };scanf("%s", arr);int i = 0;BTNode* root = CreateTree(arr, &i);InOrder(root);printf("\n");return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国赛大纲解读

1. 第一部分,是针对5G基础知识的掌握,第二部分是人工智能基本算法的掌握,就是人工智能的应用,用5G+人工智能(AI算法)进行网络优化的问题,要有网络优化的基础知识,比如说:某个区域的覆盖问题,覆盖特别差,但有数据,覆盖电频,srp值这些数据给你,根据数据来判断是…

openssl AF_ALG引擎使用

cmd AF_ALG是Linux提供的一种虚拟接口&#xff0c;用于访问内核中的加密算法。在Linux中&#xff0c;可以使用AF_ALG接口配合加密算法框架&#xff08;Crypto API&#xff09;来进行加密操作。 以下是一个使用AF_ALG和openssl进行加密操作的例子&#xff1a; # 加密 openssl…

我的编程之路:从非计算机专业到Java开发工程师的成长之路 | 学习路线 | Java | 零基础 | 学习资源 | 自学

小伙伴们好&#xff0c;我是「 行走的程序喵」&#xff0c;感谢您阅读本文&#xff0c;欢迎三连~ &#x1f63b; 【Java基础】专栏&#xff0c;Java基础知识全面详解&#xff1a;&#x1f449;点击直达 &#x1f431; 【Mybatis框架】专栏&#xff0c;入门到基于XML的配置、以…

Win10或Win11系统下西门子TIA博途运行时卡顿缓慢的解决办法总结

Win10或Win11系统下西门子TIA博途运行时卡顿缓慢的解决办法总结 首先,可以看下TIA PORTAL V19的安装条件: 处理器:Intel i5-8400H,2.5-4.2GHZ,4核以上+超线程技术,智能缓存; 内存:至少16GB,大型项目需要32GB 硬盘:必须SSD固态硬盘,至少50GB的可用空间 图形分辨率:1…

PostgreSQL FDW(外部表) 简介

1、FDW: 外部表 背景 提供外部数据源的透明访问机制。PostgreSQL fdw(Foreign Data Wrapper)是一种外部访问接口,可以在PG数据库中创建外部表,用户访问的时候与访问本地表的方法一样,支持增删改查。 而数据则是存储在外部,外部可以是一个远程的pg数据库或者其他数据库(…

LVS负载均衡-DR模式配置

LVS&#xff1a;Linux virtual server ,即Linux虚拟服务器 LVS自身是一个负载均衡器&#xff08;Director&#xff09;&#xff0c;不直接处理请求&#xff0c;而是将请求转发至位于它后端的真实服务器real server上。 LVS是四层&#xff08;传输层 tcp/udp&#xff09;负载均衡…

数据结构——二叉搜索树详解

一、二叉搜索树定义 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 1.非空左子树上所有节点的值都小于根节点的值。 2.非空右子树上所有节点的值都大于根节点的值。 3.左右子树也都为二叉搜索树。 如下图所示&#xff1a…

振弦采集仪在预防地质灾害监测中的作用与应用前景

振弦采集仪在预防地质灾害监测中的作用与应用前景 振弦采集仪&#xff08;String Vibrating Sensor&#xff0c;简称SVM&#xff09;是一种用于地质灾害监测的重要仪器&#xff0c;它通过测量地面振动信号来预测和预警地质灾害的发生。SVM的作用在于提供实时、准确的地质灾害监…

vue3+ts+element home页面侧边栏+头部组件+路由组件组合页面教程

文章目录 效果展示template代码script代码样式代码 效果展示 template代码 <template><el-container class"home"><el-aside class"flex" :style"{ width: asideDisplay ? 70px : 290px }"><div class"aside-left&q…

深度学习语义分割篇——DeepLabV1原理详解篇

&#x1f34a;作者简介&#xff1a;秃头小苏&#xff0c;致力于用最通俗的语言描述问题 &#x1f34a;专栏推荐&#xff1a;深度学习网络原理与实战 &#x1f34a;近期目标&#xff1a;写好专栏的每一篇文章 &#x1f34a;支持小苏&#xff1a;点赞&#x1f44d;&#x1f3fc;、…

数据库是怎么做到事务回滚的呢?

数据库实现事务回滚的原理涉及到数据库管理系统&#xff08;DBMS&#xff09;如何维护事务的一致性和持久性。 基本原理&#xff1a; ACID属性&#xff1a;事务的原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Iso…

【Linux】从零开始认识进程 — 中下篇

送给大家一句话&#xff1a; 人一切的痛苦&#xff0c;本质上都是对自己无能的愤怒。而自律&#xff0c;恰恰是解决人生痛苦的根本途径。—— 王小波 从零认识进程 1 进程优先级1.1 什么是优先级1.2 为什么要有优先级1.3 Linux优先级的特点 && 查看方式1.4 其他概念 2…

c++的学习之路:5、类和对象(1)

一、面向对象和面向过程 在说这个定义时&#xff0c;我就拿c语言举例&#xff0c;在c语言写程序的时候&#xff0c;基本上就是缺什么函数&#xff0c;就去手搓一个函数&#xff0c;写的程序也只是调用函数的&#xff0c;而c就是基于面向对象的开发&#xff0c;他关注的不再是单…

picgo启动失败解决

文章目录 报错信息原因分析解决方案 报错信息 打开Picgo&#xff0c;显示报错 A JavaScript error occurred in the main process Uncaught Exception: Error:ENOENT:no such file or directory,open ‘C:\Users\koko\AppData\Roaming\picgo\data.json\picgo.log’ 原因分析…

[iOS]GCD(一)

[iOS]GCD(一) 文章目录 [iOS]GCD(一)GCD的概要GCD的APIDispatch Queuedispatch_queue_createMain Dispatch Queue和 Global Dispatch Queue.Main Dispatch_set_target_queuedispatch_afterDispatch Groupdispatch_barrier_asyncdispatch_applydispatch_applydispatch_suspend/d…

【功能实现】新年贺卡(蓝桥)

题目分析&#xff1a; 想要实现一个随机抽取功能 功能拆解&#xff1a;题目给了数组&#xff0c;我们采用生成随机数的方式&#xff0c;随机数作为数组的索引值访问数组的值。 并返回获取到的值&#xff0c;将获取到的值插入到页面中。 document.addEventListener(DOMConten…

哪款软件适合做书单的背景图片?安利这3款

哪款软件适合做书单的背景图片&#xff1f;在数字化时代&#xff0c;书单作为推广阅读文化、分享书籍信息的重要载体&#xff0c;其视觉效果与内容的吸引力同等重要。一个精美的书单背景图片&#xff0c;不仅能够吸引读者的眼球&#xff0c;还能增强书单的传播效果。因此&#…

Redis 教程系列之Redis 集群配置(十三)

1.Redis集群方案比较 主从模式 在软件的架构中,主从模式(Master-Slave)是使用较多的一种架构。主(Master)和从(Slave)分别部署在不同的服务器上,当主节点服务器写入数据时,同时也会将数据同步至从节点服务器,通常情况下,主节点负责写入数据,而从节点负责读取数据。…

Java I/O

什么是 IO流&#xff1f; 存储和读取数据的解决方案 I: input O: output 流&#xff1a;像水流一样传输数据 IO流的作用&#xff1f; 用于读写数据&#xff08;本地文件&#xff0c;网络&#xff09; IO流从 传输方式 分类 字符是给人看的&#xff0c;字节是给计算机看的。 …

八、C#计数排序算法

简介 计数排序是一种非比较性的排序算法&#xff0c;适用于排序一定范围内的整数。它的基本思想是通过统计每个元素的出现次数&#xff0c;然后根据元素的大小依次输出排序结果。 实现原理 首先找出待排序数组中的最大值max和最小值min。 创建一个长度为max-min1的数组count…