C语言实现数据结构之堆

文章目录

    • 一. 树概念及结构
      • 1. 树的概念
      • 2. 树的相关概念
      • 3. 树的表示
      • 4. 树在实际中的运用(表示文件系统的目录树结构)
    • 二. 二叉树概念及结构
      • 1. 概念
      • 2. 特殊的二叉树
      • 3. 二叉树的性质
      • 4. 二叉树的存储结构
    • 三. 二叉树的顺序结构及实现
      • 1. 二叉树的顺序结构
      • 2. 堆的概念及结构
      • 3. 建堆时间复杂度
      • 4. 堆的实现
        • 4.1 结构体部分
        • 4.2 初始化 HPInit
        • 4.3 销毁 HPDestroy
        • 4.4 交换 Swap
        • 4.5 堆的插入 HPPush
        • 4.6 堆底元素向上调整 AdjustUp
        • 4.7 堆的删除 HPPop
        • 4.8 堆顶元素向下调整算法 AdjustDown
        • 4.9 返回堆顶元素 HPTop
        • 4.10 判空 HPEmpty
        • 4.11 堆排序 HeapSort
      • 5. 堆的应用
        • 5.1 堆排序
        • 5.2 TOP-K问题
    • 四. 参考代码
      • Heap.h
      • Heap.c
      • test.c

一. 树概念及结构

1. 树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

  • 有一个特殊的结点,称为根结点,根结点没有前驱结点
  • 除根结点外,其余结点被分成M(M>0)个互不相交的集合 T 1 、 T 2 、 … … 、 T m T_1、T_2、……、T_m T1T2……Tm,其中每一个集合 T i ( 1 < = i < = m ) T_i(1<= i<=m) Ti(1<=i<=m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  • 因此,树是递归定义的。

注意:树形结构中,子树之间不能有交集,否则就不是树形结构
树与非树

2. 树的相关概念

树

  • 结点的度:一个结点含有的子树的个数称为该结点的度; 如上图:A的度为6
  • 叶结点或终端结点:度为0的结点称为叶结点; 如上图:B、C、H、I…等结点为叶结点
  • 非终端结点或分支结点:度不为0的结点; 如上图:D、E、F、G…等结点为分支结点
  • 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点
  • 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点
  • 兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
  • 树的度:一棵树中,最大的结点的度称为树的度; 如上图:树的度为6
  • 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  • 树的高度或深度:树中结点的最大层次; 如上图:树的高度为4
  • 堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点
  • 结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
  • 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
  • 森林:由m(m>0)棵互不相交的树的集合称为森林;

3. 树的表示

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既要保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。我们这里就简单的了解其中最常用的孩子兄弟表示法

typedef int DataType;
struct Node
{struct Node* firstChild1; // 第一个孩子结点struct Node* pNextBrother; // 指向其下一个兄弟结点DataType data; // 结点中的数据域
};

孩子兄弟表示法

4. 树在实际中的运用(表示文件系统的目录树结构)

linux树状目录结构

二. 二叉树概念及结构

1. 概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 由一个根结点加上两棵别称为左子树和右子树的二叉树组成
    根与左右子树

从上图可以看出:

  1. 二叉树不存在度大于2的结点
  2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
    注意:对于任意的二叉树都是由以下几种情况复合而成的:
    树的特殊情况

2. 特殊的二叉树

  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是 2 k − 1 2^k -1 2k1 ,则它就是满二叉树。
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
    满二叉树与完全二叉树

3. 二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第 i i i层上最多有 2 ( i − 1 ) 2^{(i-1)} 2(i1)个结点.
  2. 若规定根结点的层数为1,则深度为 h h h的二叉树的最大结点数是 2 h − 1 2^h-1 2h1.
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为 n 0 n_0 n0, 度为2的分支结点个数为 n 2 n_2 n2,则有 n 0 = n 2 + 1 n_0=n_2+1 n0n21
/*
* 假设二叉树有N个结点
* 从总结点数角度考虑:N = n0 + n1 + n2 ①
*
* 从边的角度考虑,N个结点的任意二叉树,总共有N-1条边
* 因为二叉树中每个结点都有双亲,根结点没有双亲,每个节点向上与其双亲之间存在一条边
* 因此N个结点的二叉树总共有N-1条边
* 因为度为0的结点没有孩子,故度为0的结点不产生边; 度为1的结点只有一个孩子,故每个度
* 为1的结点产生一条边; 度为2的结点有2个孩子,故每个度为2的结点产生两条边,所以总边
* 为:n1+2*n2
* 故从边的角度考虑:N-1 = n1 + 2*n2 ②
* 结合① 和 ②得:n0 + n1 + n2 = n1 + 2*n2 - 1
* 即:n0 = n2 + 1
*/
  1. 若规定根结点的层数为1,具有n个结点的满二叉树的深度 h = l o g 2 ( n + 1 ) h= log_2(n + 1) h=log2(n+1). (ps: h = l o g 2 ( n + 1 ) h= log_2(n + 1) h=log2(n+1)是log以2为底,n+1为对数)
  2. 对于具有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. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )
    A 不存在这样的二叉树
    B 200
    C 198
    D 199
  2. 下列数据结构中,不适合采用顺序存储结构的是( )
    A 非完全二叉树
    B 堆
    C 队列
    D 栈
  3. 在具有 2n 个结点的完全二叉树中,叶子结点个数为( )
    A n
    B n+1
    C n-1
    D n/2
  4. 一棵完全二叉树的结点数位为531个,那么这棵树的高度为( )
    A 11
    B 10
    C 8
    D 12
  5. 一个具有767个结点的完全二叉树,其叶子结点个数为()
    A 383
    B 384
    C 385
    D 386

答案:
1.B
2.A
3.A
4.B
5.B

4. 二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。

  1. 顺序存储
    顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树
    二叉树的顺序存储

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

typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{struct BinTreeNode* left; // 指向当前结点左孩子struct BinTreeNode* right; // 指向当前结点右孩子BTDataType data; // 当前结点值域
}
// 三叉链
struct BinaryTreeNode
{struct BinTreeNode* parent; // 指向当前结点的双亲struct BinTreeNode* left; // 指向当前结点左孩子struct BinTreeNode* right; // 指向当前结点右孩子BTDataType data; // 当前结点值域
}

三. 二叉树的顺序结构及实现

1. 二叉树的顺序结构

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

2. 堆的概念及结构

如果有一个关键码的集合K = { k 0 k_0 k0 k 1 k_1 k1 k 2 k_2 k2,…, k n − 1 k_{n-1} kn1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: k i < = k 2 i + 1 k_i<=k_{2i + 1} ki<=k2i+1 k i < = k 2 i + 2 k_i<=k_{2i + 2} ki<=k2i+2 ( k i > = k 2 i + 1 k_i>=k_{2i + 1} ki>=k2i+1 k i > = k 2 i + 2 k_i>=k_{2i + 2} ki>=k2i+2 ) i = 0,1,2…,则称为小堆(或大堆)。将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。

堆的性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值
  • 堆总是一棵完全二叉树

3. 建堆时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个结点不影响最终结果):
建堆时间复杂度

因此:建堆的时间复杂度为O(N)

选择题
1.下列关键字序列为堆的是:()
A 100,60,70,50,32,65
B 60,70,65,50,32,100
C 65,100,70,32,50,60
D 70,65,100,32,50,60
E 32,50,100,70,65,60
F 50,100,70,65,60,32
2.已知小根堆为8,15,10,21,34,16,12,删除关键字 8 之后需重建堆,在此过程中,关键字之间的比较次数是()。
A 1
B 2
C 3
D 4
3.一组记录排序码为(5 11 7 2 3 17),则利用堆排序方法建立的初始堆为
A(11 5 7 2 3 17)
B(11 5 7 2 17 3)
C(17 11 7 2 3 5)
D(17 11 7 5 3 2)
E(17 7 11 3 5 2)
F(17 7 11 3 2 5)
4.最小堆[0,3,2,5,7,4,6,8],在删除堆顶元素0之后,其结果是()
A[3,2,5,7,4,6,8]
B[2,3,5,7,4,6,8]
C[2,3,4,5,7,8,6]
D[2,3,4,5,6,7,8]

选择题答案

  1. A
  2. C
  3. C
  4. C

4. 堆的实现

typedef int HPDataType;
typedef struct Heap
{
HPDataType* _a;
int _size;
int _capacity;
}Heap;
// 堆的构建
void HeapCreate(Heap* hp, HPDataType* a, int n);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);
4.1 结构体部分

堆的实现我们按照动态顺序表为物理结构(即顺序存储结构),以完全二叉树为逻辑结构。

typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;
4.2 初始化 HPInit

下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根结点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子结点的子树开始调整,一直调整到根结点的树,就可以调整成堆。

int a[] = {1,5,3,8,7,6};
void HPInit(HP* php)
{assert(php);php->a = NULL;php->size = 0;php->capacity = 0;
}
4.3 销毁 HPDestroy
void HPDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = 0;php->capacity = 0;
}
4.4 交换 Swap

这里我们实现一个交换函数,方便我们后续对堆的元素进行调整。

void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}
4.5 堆的插入 HPPush

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。

void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* newa = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));if (newa == NULL){perror("realloc failed!\n");exit(1);}php->a = newa;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}

现在,我们只是把一个元素插入到了数组之中,接下来,我们要对该元素进行向上调整。

4.6 堆底元素向上调整 AdjustUp

向上调整

void AdjustUp(HPDataType* a, int child)//向上调整
{int parent = (child - 1) / 2;//小堆//while (parent >= 0)while(child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);//交换child = parent;parent = (child - 1) / 2;}else{break;}}
}
4.7 堆的删除 HPPop

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。
堆的删除

//时间复杂度:O(logN)
void HPPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);
}

现在,我们也同样只是把堆顶元素(根位置元素)从数组中删除,接下来的向下调整算法,才是堆的核心算法,也是堆排序的核心算法。

4.8 堆顶元素向下调整算法 AdjustDown

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根结点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

int array[] = {27,15,19,18,28,34,65,49,25,37};

堆向下调整算法

void AdjustDown(HPDataType* a,int n, int parent)//堆顶元素向下调整
{//假设左孩子小int child = parent * 2 + 1;while (child < n)//如果child >= n,说明孩子不存在,调整到叶子了{//找出小的那个孩子if (child + 1 < n && a[child + 1] < a[child])//防止越界{++child;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
4.9 返回堆顶元素 HPTop
HPDataType HPTop(HP* php)
{assert(php);return php->a[0];
}
4.10 判空 HPEmpty
_Bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
4.11 堆排序 HeapSort
void HeapSort(HPDataType* a, int n)
{//建堆//降序 -- 建小堆//升序 -- 建大堆//for (int i = 1; i < n; i++)//{//	AdjustUp(a, i);//}//建堆//从最后一个父亲节点开始,依次向上执行向下调整算法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;}
}

5. 堆的应用

5.1 堆排序

堆排序即利用堆的思想来进行排序,总共分为两个步骤:

  1. 建堆
    升序:建大堆
    降序:建小堆
  2. 利用堆删除思想来进行排序
    建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。
5.2 TOP-K问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

  1. 用数据集合中前K个元素来建堆
    前k个最大的元素,则建小堆
    前k个最小的元素,则建大堆
  2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。
void PrintTopK(int* a, int n, int k)
{// 1. 建堆--用a中前k个元素建堆// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc fail");return;}// 读取数组中前k个数for (int i = 0; i < k; i++){kminheap[i] = a[i];}// 建K个数的小堆for (int i = (k-1-1)/2; i>=0 ; i--){AdjustDown(kminheap, k, i);}// 读取剩下的N-K个数int x = k;while (x < n){if (x > kminheap[0]){kminheap[0] = x;AdjustDown(kminheap, k, 0);}}printf("最大前%d个数:", k);for (int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}void TestTopk()
{int n = 10000;int* a = (int*)malloc(sizeof(int)*n);srand(time(0));//造数据for (size_t i = 0; i < n; ++i){a[i] = rand() % 1000000;}//人为创造最大的大数a[5] = 1000000 + 1;a[1231] = 1000000 + 2;a[531] = 1000000 + 3;a[5121] = 1000000 + 4;a[115] = 1000000 + 5;a[2335] = 1000000 + 6;a[9999] = 1000000 + 7;a[76] = 1000000 + 8;a[423] = 1000000 + 9;a[3144] = 1000000 + 10;PrintTopK(a, n, 10);
}

四. 参考代码

Heap.h

#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 HPInit(HP* php);void HPDestroy(HP* php);//插入数据
void HPPush(HP* php, HPDataType x);//删除堆顶元素(根位置)
void HPPop(HP* php);//返回堆顶元素
HPDataType HPTop(HP* php);//判空
_Bool HPEmpty(HP* php);//堆底元素向上调整
void AdjustUp(HPDataType* a, int child);//堆顶元素向下调整
void AdjustDown(HPDataType* a, int n, int parent);//交换
void Swap(HPDataType* p1, HPDataType* p2);

Heap.c

#include "Heap.h"void HPInit(HP* php)
{assert(php);php->a = NULL;php->size = 0;php->capacity = 0;
}void HPDestroy(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 (parent >= 0)while(child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);//交换child = parent;parent = (child - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* newa = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));if (newa == NULL){perror("realloc failed!\n");exit(1);}php->a = newa;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}void AdjustDown(HPDataType* a,int n, int parent)//堆顶元素向下调整
{//假设左孩子小int child = parent * 2 + 1;while (child < n)//如果child >= n,说明孩子不存在,调整到叶子了{//找出小的那个孩子if (child + 1 < n && a[child + 1] < a[child])//防止越界{++child;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}//时间复杂度:O(logN)
void HPPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);
}HPDataType HPTop(HP* php)
{assert(php);return php->a[0];
}_Bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

test.c

#include "Heap.h"
#include "vld.h"void TestHeap01()
{int a[10] = { 2,3,4,1,6,5,9,8,7,0 };HP hp;HPInit(&hp);size_t sz = sizeof(a) / sizeof(int);for (size_t i = 0; i < sz; i++){HPPush(&hp, a[i]);}int i = 0;while (!HPEmpty(&hp)){//printf("%d ", HPTop(&hp));a[i++] = HPTop(&hp);HPPop(&hp);}HPDestroy(&hp);
}void HeapSort(HPDataType* a, int n)
{//建堆//降序 -- 建小堆//升序 -- 建大堆//for (int i = 1; i < n; i++)//{//	AdjustUp(a, i);//}//建堆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;}
}//排序
//void HeapSort(HPDataType* a, int n);void TestHeap02()
{int a[10] = { 2,3,4,1,6,5,9,8,7,0 };size_t sz = sizeof(a) / sizeof(int);HeapSort(a, sz);for (int i = 0; i < sz; i++){printf("%d ", a[i]);}printf("\n");}int main()
{//TestHeap01();TestHeap02();return 0;
}

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

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

相关文章

如何关闭 Ubuntu22.04 LTS 的更新提醒

引言 众所周知&#xff0c;Ubuntu 的软件更新和版本更新提醒是又多又烦&#xff0c;如果不小心更新到了最新的 Ubuntu 还可能面临各种各样的问题&#xff0c;这里提供一个解决方法 步骤 首先按照下面步骤打开 Software & Updates 然后按照下面步骤依次点击 最后关闭即可…

CS61b part5

8.1 The Desire for Generality 今天我们将会讨论一个全新的主题&#xff0c;称为继承。为了铺垫&#xff0c;让我们考虑在过去几节课中构建的SList类和AList类。我们看到它们实际上具有完全相同的操作&#xff0c;它们都允许我们添加元素、获取元素、移除元素以及获取大小&am…

隆盛策略正规股票杠杠交易市场A股,盘中突变…

突然跌了。 查查配分析A股市场今天大幅高开,上证指数一度重返3500点之上,临近午盘,该指数翻绿。TMT赛道掀起涨停潮,成为上午A股市场最大亮点之一。 另外,多只近期强势股继续走强,有股票在短短9个交易日的时间股价自低位涨了约3倍。 隆盛策略以其专业的服务和较低的管理费用在…

学生公寓人走断电控制系统的设计要求

石家庄光大远通电气有限公司学生公寓人走断电系统技术背景用电器待机能耗往往是一种不易被发现的“隐藏的浪费”&#xff0c;如果将一户家庭的空调、洗衣机、电视、微波炉、电饭煲五类电器进行计算&#xff0c;待机功率在12W到15W&#xff0c;待机能耗0.2度到0.33度电。每年能耗…

解决yum命令报错“Could not resolve host: mirrorlist.centos.org

这个主要是yum源出了问题或者服务器网络有问题&#xff0c;检查网络排除网络问题后&#xff0c;可更换源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.k wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.huaweicloud.com/repository…

TikTok Spark Ads火花广告是什么?如何设置?

TikTok的广告类型多样、功能各异&#xff0c;如果你需要投放精准度更高、效果更持久、更能吸引用户点击和参与的广告&#xff0c;那么Spark Ads会是一个相当不错的选择。 一、什么是TikTok Spark Ads 1.概念 Spark Ads是直接使用真实的自然流量视频及其功能来进行宣传的一种原…

微软日志丢失事件敲响安全警钟

NEWS | 事件回顾 最近&#xff0c;全球最大的软件公司之一——微软&#xff0c;遭遇了一场罕见的日志丢失危机。据报告&#xff0c;从9月2日至9月19日&#xff0c;持续长达两周的时间里&#xff0c;微软的多项核心云服务&#xff0c;包括身份验证平台Microsoft Entra、安全信息…

「QT」几何数据类 之 QRectF 浮点型矩形类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

Android音频进阶之PCM设备创建(九十三)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…

【TMM2024】Frequency-Guided Spatial Adaptation for Camouflaged Object Detection

论文链接&#xff1a;https://arxiv.org/abs/2409.12421 这个论文研究 Camouflaged Object Detection &#xff08;COD&#xff09;问题&#xff0c;作者认为&#xff0c;使用 pretrained foundation model 可以改进COD的准确率&#xff0c;但是当前的 adaptor 大多学习空间特…

大数据-208 数据挖掘 机器学习理论 - 岭回归 和 Lasso 算法 原理

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Spark Streaming

流处理和批处理 spark streaming底层原理 滑动窗口 window窗口操作二 过车数据案例

关于圆周率-3

最后一个问题&#xff0c;欧拉公式&#xff0c; 到底要说明的是什么。从欧拉函数的四个特殊值可以看出&#xff0c; 可见这个函数的作用是将角度映射回它原来的数值。在螺旋楼梯的例子中&#xff0c;我们用虚数单位的倍数搭建楼梯&#xff0c;并构造角度&#xff0c;角度是一系…

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Exe cution_Policies。 所在位置 行:1 字符: 1 npm install ~~~ CategoryInf…

WPF+MVVM案例实战与特效(二十六)- 3D粒子方块波浪墙效果实现

文章目录 1、案例效果2、案例实现1、文件创建2. 功能代码实现3、粒子功能应用1、前端布局与样式2、代码解释2、 后端功能代码1、案例效果 2、案例实现 1、文件创建 打开 Wpf_Examples 项目、Models 文件夹下创建 3D粒子模型类 ParticleCubeWaveModel.cs 文件。在Tools 文件夹…

NVR设备ONVIF接入平台EasyCVR私有化部署视频平台如何安装欧拉OpenEuler 20.3 MySQL

在当今数字化时代&#xff0c;安防视频监控系统已成为保障公共安全和个人财产安全的重要工具。NVR设备ONVIF接入平台EasyCVR作为一款功能强大的智能视频监控管理平台&#xff0c;它不仅提供了视频远程监控、录像、存储与回放等基础功能&#xff0c;还涵盖了视频转码、视频快照、…

动态规划理论基础和习题【力扣】【算法学习day.26】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

webpack 执行流程 — 实现 myWebpack

前言 实现 myWebpack 主要是为了更好的理解&#xff0c;webpack 中的工作流程&#xff0c;一切都是最简单的实现&#xff0c;不包含细节内容和边界处理&#xff0c;涉及到 ast 抽象语法树和编译代码部分&#xff0c;最好可以打印出来观察一下&#xff0c;方便后续的理解。 re…

【WRF模拟】全过程总结:WPS预处理及WRF运行

【WRF模拟】全过程总结:WPS预处理及WRF运行 1 数据准备1.1 嵌套域设置(Customize domain)-基于QGis中gis4wrf插件1.2 静态地理数据1.2.1 叶面积指数LAI和植被覆盖度Fpar(月尺度)1.2.2 地面反照率(月尺度)1.2.3 土地利用类型+不透水面积1.2.4 数据处理:geotiff→tiff(W…