当前位置: 首页 > news >正文

企业网站如何建设/路由优化大师

企业网站如何建设,路由优化大师,汉鼎宇佑建设投资网站,邵阳网站建设设计目录 前言 一.堆的介绍 1.堆的本质 2.堆的分类 二.堆的实现(以小根堆为例) 1.关于二叉树的两组重要结论: 2.堆的物理存储结构框架(动态数组的简单构建) 3. 堆元素插入接口(以小根堆为例) 堆尾元素向上调整的算法接口: 4.堆元素插入接口测试 5.堆元素插入…

目录

前言

一.堆的介绍

1.堆的本质

2.堆的分类

二.堆的实现(以小根堆为例)

1.关于二叉树的两组重要结论:

2.堆的物理存储结构框架(动态数组的简单构建)

3. 堆元素插入接口(以小根堆为例)

堆尾元素向上调整的算法接口:

4.堆元素插入接口测试

5.堆元素插入接口建堆的时间复杂度分析(建堆时间复杂度)

6.堆元素删除接口(同样以小根堆为例子)

堆元素向下调整算法接口实现:

7.堆元素删除接口测试

8.逐个删除堆顶数据过程的时间复杂度分析(删堆的时间复杂度分析)

9.堆的实现代码总览(以小根堆为例)

10.结语

 

 


前言

关于数据结构的文章:写博客的时候我感觉在表达层面上有点费劲,如果文章整体在表述上让人感觉不够清楚,恳请读者原谅,本菜狗已经尽力了.

一.堆的介绍

1.堆的本质

关于二叉树的图论基础参见:http://t.csdn.cn/Nv325http://t.csdn.cn/Nv325青菜友情提示:基础概念对于理解堆的实现与运用非常重要

堆的本质映射内存中顺序存储结构(数组)上的完全二叉树(完全二叉树是堆的逻辑结构).

堆的图解:

  • 结点中的数据存储在相应下标的数组元素空间中

2.堆的分类

堆的两个类型:

  1. 大根堆:在大根堆中任何子结构的父结点中存储的值大于左右孩子结点中存储的值
  2. 小根堆:小根堆中任何子结构的父结点中存储的值小于左右孩子结点中存储的值

二.堆的实现(以小根堆为例)

1.关于二叉树的两组重要结论:

  • 堆的任何一个父结点的编号parent与其左孩子结点的编号leftchild满足如下关系式:
  • 堆的任何一个父结点的编号parent与其右孩子结点的编号rightchild满足如下关系式:

这两组重要结论的推导和分析参见青菜的博客:http://t.csdn.cn/Nv325http://t.csdn.cn/Nv325

2.堆的物理存储结构框架(动态数组的简单构建)

堆是存储在数组上的(大小根)完全二叉树,因此在实现堆之前我们先构建一个简单的动态数组作为物理存储结构框架:

  • 维护动态数组的结构体:
    typedef int HPDataType;   //堆元素类型
    typedef struct Heap
    {HPDataType* arry;     //堆区内存指针size_t size;          //堆元素个数size_t capacity;      //数组的空间容量
    }HP;
    
  • 堆的基础操作接口声明:
    //维护堆的结构体的初始化接口
    void HeapInit(HP* php);//销毁堆的接口
    void HeapDestroy(HP* php);//堆元素的打印接口
    void HeapPrint(HP* php);//判断堆是否为空(堆中有无元素)的接口
    bool HeapEmpty(HP* php);//返回堆中元素个数的接口
    size_t HeapSize(HP* php);//返回堆顶元素(即编号为0的元素)的接口
    HPDataType HeapTop(HP* php);
  • 基础接口的实现:
    //堆结构体的初始化接口
    void HeapInit(HP* ptrheap)
    {assert(ptrheap);ptrheap->arry = NULL;ptrheap->capacity = 0;ptrheap->size = 0;}//销毁堆的接口
    void HeapDestroy(HP* ptrheap)
    {assert(ptrheap);free(ptrheap->arry);ptrheap->arry = NULL;ptrheap->capacity = 0;ptrheap->size = 0;
    }//堆的打印接口
    void HeapPrint(HP* ptrheap)
    {assert(ptrheap);size_t tem = 0;for (tem = 0; tem < ptrheap->size; ++tem){printf("%d->", ptrheap->arry[tem]);}printf("END\n");
    }//判断堆是否为空的接口
    bool HeapEmpty(HP* ptrheap)
    {assert(ptrheap);return (0 == ptrheap->size);
    }//返回堆元素个数的接口
    size_t HeapSize(HP* ptrheap)
    {assert(ptrheap);return ptrheap->size;
    }//返回堆顶元素的接口
    HPDataType HeapTop(HP* ptrheap)
    {assert(!HeapEmpty(ptrheap));return ptrheap->arry[0];
    }

    主函数建堆时的内存布局简单图示:

    堆区上的数组是在堆元素插入接口中调用malloc申请出来的(我们暂时还没有实现堆元素插入的接口)

  • 以上是堆在内存中的存储框架的构建,然而堆的核心接口是堆元素的插入和删除接口

3. 堆元素插入接口(以小根堆为例)

  • 堆的构建过程概述:向堆尾逐个插入元素(将元素尾插进数组中),每次插入一个元素后都通过堆的调整算法逐层向上(二叉树意义上的层)(子结点和父结点进行大小比较,若不满足小根堆的性质就进行数值交换)调整该元素在堆中的位置以保持小根堆的数据结构.
  • 算法过程简图:
  • 从0个结点的堆开始,每尾插一个元素我们都按照小根堆的性质(通过元素向上调整算法)调整该元素在堆中的位置来保持小根堆的数据结构,我们就是以这样的基本思想来建堆的.
  • 建堆的思路细解:

  • 显然在堆尾插入元素6后破坏了小根堆的结构(6小于其父结点20不满足小根堆的性质)(任意一个子结构中子结点与父结点进行大小比较就可以知道堆的结构有没有被破坏),因此我们就需要将6这个元素逐层向二叉树的上层调整(每个调整的子步骤都是从子结点向父结点调整)
  • 通过树的子结构中子结点与父结点的编号关系可以找到堆尾8号结点(元素6)的父结点(元素20,结点编号为3)
  • 接下来将元素逐层向上调整(子结点和父结点进行数值交换)恢复小根堆的数据结构:

向上调整的第一步:将尾插进堆尾的结点(8号结点,值为6)与其父结点(3号结点,值为20)进行比较,父结点大于子结点,交换父结点与子结点的值(下图中的Swap是元素数值交换接口):

向上调整的第二步:交换了8号结点和3号结点的值后,我们发现小堆结构依然不成立,于是重复上述的调整过程,将元素6继续向上层的父结点位置进行调整,不断重复迭代直到小堆结构恢复或者元素6被调到堆顶为止:

  • 可见经过再一次调整后,元素6来到了1号结点,此时1号结点大于0号结点,小堆数据结构得到恢复,调整过程终止。

同时不难分析出,任何堆尾元素向上调整的过程都是在堆尾到堆顶元素的连通路径上进行的(该路径长度数量级为logk)(k为当前树结点总个数)):

  • 根据上面的分析我们可以设计出一个堆尾元素向上调整的算法接口:

接口首部: arry是指向数组首地址的指针,child是堆尾元素的编号(结点编号同时也是该元素的数组下标)

void AdjustUp(HPDataType* arry, size_t child);

堆尾元素向上调整的算法接口:

//元素交换接口
void Swap(HPDataType* e1, HPDataType* e2)
{assert(e1 && e2);HPDataType tem = *e1;*e1 = *e2;*e2 = tem;
}//小堆元素的向上调整接口
void AdjustUp(HPDataType* arry, size_t child)  //child表示孩子结点的编号
{assert(arry);size_t parent = (child - 1) / 2;    //算出父结点的数组下标(堆编号)while (child > 0)			        //child减小到0时则调整结束(堆尾元素已调到堆顶){if (arry[child] < arry[parent]) //父结点大于子结点,则子结点需要上调以保持小堆的结构{Swap(arry + child, arry+parent);child = parent;				//将原父结点作为新的子结点继续迭代过程parent = (child - 1) / 2;	//算出父结点的数组下标(堆编号)}else{break;						//父结点不大于子结点,则堆结构恢复,无需再调整}}
}

堆尾元素向上调整的算法接口中需要注意的细节:

  • 调整循环的终止条件有两个:
  1. 一个是被调整元素被调到了堆顶(即child=0的时候)
  2. 被调整元素大于其父结点时小堆的数据结构得到恢复,break终止循环

有了该接口,我们就可以设计堆元素插入接口:

  • HP * ptrheap是指向堆结构体的结构体指针,x是要插入的元素的数值
void HeapPush(HP* ptrheap, HPDataType x)
// 插入一个小堆元素的接口
// 插入x以后,保持其数据结构依旧是小堆
void HeapPush(HP* ptrheap, HPDataType x)        //ptrheap是指向堆结构体的结构体指针
{assert(ptrheap);if (ptrheap->capacity == ptrheap->size)	    //数组容量检查,容量不够则扩容{size_t newcapacity = (0 == ptrheap->capacity) ? 4 : 2 * ptrheap->capacity;//注意容量为0则将堆区数组容量调整为4HPDataType* tem = (HPDataType*)realloc(ptrheap->arry, newcapacity*sizeof(HPDataType)); //空间不够则扩容assert(tem);             //检查扩容是否成功ptrheap->arry = tem;     //将堆区地址赋给结构体中的指针成员ptrheap->capacity = newcapacity; //容量标记更新}ptrheap->arry[ptrheap->size] = x;			//元素尾插入堆ptrheap->size++;//将尾插的元素进行向上调整以保持堆的数据结构(复用元素向上调整接口)AdjustUp(ptrheap->arry, ptrheap->size - 1); //根据完全二叉树的结构特点可知堆尾元素                //在二叉树中编号为size-1
}
  • 该接口可以完成一个堆元素的插入(而且每次完成插入后小根堆的数据结构都可以得到保持)
  • 如果我们想要创建一个n个元素小根堆,则n次调用HeapPush接口即可

4.堆元素插入接口测试

现在我们试着用HeapPush接口来构建六个元素的小堆,并将堆打印出来观察其逻辑结构:

  • 主函数代码:
    int main ()
    {HP hp;              //创建一个堆结构体HeapInit(&hp);      //结构体初始化HeapPush(&hp, 1);   //调用堆元素插入接口建堆HeapPush(&hp, 5);HeapPush(&hp, 0);HeapPush(&hp, 8);HeapPush(&hp, 3);HeapPush(&hp, 9);HeapPrint(&hp);     //打印堆元素
    }

    我们来观察一下打印出来的小根堆的逻辑结构:

5.堆元素插入接口建堆的时间复杂度分析(建堆时间复杂度)

  • 假设现在我们要调用HeapPush接口创建一个N个元素的小堆(调用N次HeapPush接口)
  • 注意:我们只关注时间复杂度最坏的情况(即假设每个插入堆尾的元素都沿着连通路径向上调整到了堆顶)
  • 分析建堆的时间复杂度时我们将堆看成满二叉树(满二叉树是特殊的完全二叉树),也就是说当堆有N个元素时,堆的层数h=log(N+1)(该对数以2为底,计算机科学中我们一般不关注对数的底数)
  • 接下来我们将所有元素的向上调整次数进行求和,即可得出用HeapPush接口建堆的时间复杂度:
  • 错位相减法可对上面公式进行求和计算:
  • 因此可以得到用堆元素插入接口(堆元素向上调整算法)建堆(建立N个元素的小根堆)的时间复杂度为:O(N)=NlogN;

6.堆元素删除接口(同样以小根堆为例子)

我们讨论的堆元素删除指的是:删除堆顶数据

删除堆顶的元素的基本思路:

  • 将堆顶元素与堆尾元素进行交换,然后令维护堆的结构体中的size(记录堆元素个数的成员变量)减一(相当于移除堆尾元素)
  • 然而原来的堆尾元素被交换到堆顶位置后,小根堆的数据结构会被破坏,因此我们需要将堆顶元素进行向下调整操作:
  • 堆顶元素向下调整图解演示:
  • 通过算法图解分析我们可以设计一个堆元素向下调整算法接口: 

arry是指向内存堆区数组首地址的指针,size是堆的结点总个数,parent是待调整结点在堆中的编号;

void AdjustDown(HPDataType* arry,size_t size,size_t parent)

堆元素向下调整算法接口实现:

//元素交换接口
void Swap(HPDataType* e1, HPDataType* e2)
{assert(e1 && e2);HPDataType tem = *e1;*e1 = *e2;*e2 = tem;
}//小堆元素的向下调整接口
void AdjustDown(HPDataType* arry,size_t size,size_t parent)
{assert(arry);size_t child = 2 * parent + 1;   //确定父结点的左孩子的编号while (child < size)			 //child增加到大于或等于size时说明被调整元素被调整到了叶结点上,调整过程结束{if (child + 1 < size && arry[child + 1] < arry[child])//确定左右孩子中较小的孩子结点{++child;   //条件成立说明右孩子较小,child更新为右孩子编号}if ( arry[child] < arry[parent])//父结点大于子结点,则父结点需要下调以保持小堆的结构{Swap(arry + parent, arry + child);//父子结点进行值交换parent = child;				      //将原来的子结点作为新的父结点继续迭代过程child = 2 * parent + 1;		      //继续向下找另外一个子结点}else{break;						//父结点不大于子结点,则小堆结构成立,无需继续调整}}
}
  •  注意一下算法接口的一些细节和边界条件:
  1. child<size说明被调整元素已经被调整到叶结点位置,结束调整过程
  2. 算法接口中我们只设计了一个child变量记录当前父结点的孩子结点的编号,接着通过arry[child + 1] < arry[child]来比较左右孩子大小来确定child到底是取左孩子的编号还是取右孩子的编号(注意child+1<size判断语句是为了确定右孩子是否存在)
  • 有了堆元素向下调整算法接口我们就可以实现堆顶数据删除接口:
    //删除堆顶元素
    void HeapPop(HP* ptrheap)
    {assert(ptrheap);Swap(ptrheap->arry, ptrheap->arry + ptrheap->size - 1); //交换堆顶与堆尾元素ptrheap->size--;										//删除堆尾元素AdjustDown(ptrheap->arry, ptrheap->size, 0);    //将堆顶元素进行向下调整以保持堆的数据结构
    }

    注意:AdjustDown接口的传参中,ptrheadp->size指的是堆元素的总个数,由于我们要将堆顶元素向下调整,因此传入的被调整结点编号为0

  • 该接口每调用一次就可以删除一个堆顶数据(并保持小根堆的数据结构):

7.堆元素删除接口测试

我们先6次调用HeapPush接口创建一个六个元素的小堆,然后再6次调用HeapPop接口逐个删除堆顶元素(每删除一个堆顶数据打印一次堆,借此观察每次删除堆顶数据后堆的数据结构).

int main ()
{HP hp;HeapInit(&hp);HeapPush(&hp, 1);HeapPush(&hp, 5);HeapPush(&hp, 0);HeapPush(&hp, 8);HeapPush(&hp, 3);HeapPush(&hp, 9);HeapPrint(&hp);HeapPop(&hp);HeapPrint(&hp);HeapPop(&hp);HeapPrint(&hp);HeapPop(&hp);HeapPrint(&hp);HeapPop(&hp);HeapPrint(&hp);HeapPop(&hp);HeapPrint(&hp);HeapDestroy(&hp);}

观察小根堆的数据结构(逻辑结构): 

  • 可见逐个删除堆顶数据的过程中小根堆的数据结构得到了保持

8.逐个删除堆顶数据过程的时间复杂度分析(删堆的时间复杂度分析)

假设现在有一个N个元素的小根堆,我们逐个删除堆顶数据直到将堆删空

现在我们来分析这个过程的时间复杂度(我们同样将二叉树看成满二叉树来分析):

  • 同样我们考虑的是时间复杂度最坏的情况:即每次调用堆元素删除接口后,被交换到堆顶的元素都沿着连通路径向下被调整到叶结点
  • 分析:假设堆的高度为h,则满树的总结点个数N为  : 2^h - 1 
    需要注意的是满树的第h层(最后一层)的结点个数为: 2^(h-1)

所以满树的最后一层的结点个数占树的总结点个数的一半

因此如果我们删去满树的前h-1层的所有结点,则由最后一层结点所构成的新树的高度大致为h-1:

这也就意味着,在删除前h-1层结点的过程中树的总高度几乎不会发生变化:

因此可以得到删除满树的前h-1层所有结点过程中,每个被交换到堆顶的元素都要被向下调整log(N+1)次,则删除满树的前h-1层所有结点过程中,向下调整算法中循环语句执行总次数约为:

接着,对于由原树的最后一层(第h层)结点构成的新树(层数为h-1层)我们可以作类似的分析(即先删除其前h-2层结点,得到由其第h-1层结点构成的新树),以这种方式递推下去直到树被删空为止:

  • 由此可得, 逐个删除堆顶数据直到将堆删空过程中,堆元素的向下调整算法中循环语句总的执行次数估算为:

该多项式的和化为大O阶渐进表示法结果为O(NlogN). 

  • 逐个删除堆顶数据直到将堆删空的过程的时间复杂度分析为:O(NlogN)

9.堆的实现代码总览(以小根堆为例)

接口和结构类型声明的头文件:

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>//实现小堆typedef int HPDataType;
typedef struct Heap
{HPDataType* arry;size_t size;size_t capacity;
}HP;//堆的初始化接口
void HeapInit(HP* php);
//销毁堆的接口
void HeapDestroy(HP* php);
//堆的打印接口
void HeapPrint(HP* php);
//判断堆是否为空的接口
bool HeapEmpty(HP* php);
//返回堆元素个数的接口
size_t HeapSize(HP* php);
//返回堆顶元素的接口
HPDataType HeapTop(HP* php);void Swap(HPDataType* pa, HPDataType* pb);
//堆元素向上调整算法接口
void AdjustUp(HPDataType* a, size_t child);
//堆元素向下调整算法接口
void AdjustDown(HPDataType* a, size_t size,size_t parent);
// 插入元素x以后,保持数据结构是(大/小)堆
void HeapPush(HP* php, HPDataType x);
// 删除堆顶的数据后,保持数据结构是(大/小)堆
void HeapPop(HP* php);

各个堆操作接口的实现:

#include "heap.h"//堆的初始化接口
void HeapInit(HP* ptrheap)
{assert(ptrheap);ptrheap->arry = NULL;ptrheap->capacity = 0;ptrheap->size = 0;}
//销毁堆的接口
void HeapDestroy(HP* ptrheap)
{assert(ptrheap);free(ptrheap->arry);ptrheap->arry = NULL;ptrheap->capacity = 0;ptrheap->size = 0;
}//堆的打印接口
void HeapPrint(HP* ptrheap)
{assert(ptrheap);size_t tem = 0;for (tem = 0; tem < ptrheap->size; ++tem){printf("%d->", ptrheap->arry[tem]);}printf("END\n");
}//判断堆是否为空的接口
bool HeapEmpty(HP* ptrheap)
{assert(ptrheap);return (0 == ptrheap->size);
}//返回堆元素个数的接口
size_t HeapSize(HP* ptrheap)
{assert(ptrheap);return ptrheap->size;
}//返回堆顶元素的接口
HPDataType HeapTop(HP* ptrheap)
{assert(!HeapEmpty(ptrheap));return ptrheap->arry[0];
}//元素交换接口
void Swap(HPDataType* e1, HPDataType* e2)
{assert(e1 && e2);HPDataType tem = *e1;*e1 = *e2;*e2 = tem;
}//小堆元素的向上调整接口
void AdjustUp(HPDataType* arry, size_t child)  //child表示孩子结点的编号
{assert(arry);size_t parent = (child - 1) / 2;while (child > 0)						   //child减小到0时则调整结束{if (arry[child] < arry[parent])        //父结点大于子结点,则子结点需要上调以保持小堆的结构{Swap(arry + child, arry+parent);child = parent;				//将原父结点作为新的子结点继续迭代过程parent = (child - 1) / 2;	//继续向上找另外一个父结点}else{break;						//父结点不大于子结点,则堆结构任然成立,无需调整}}
}// 插入一个小堆元素的接口
// 插入x以后,保持其数据结构依旧是小堆
void HeapPush(HP* ptrheap, HPDataType x)
{assert(ptrheap);if (ptrheap->capacity == ptrheap->size)	//容量检查,容量不够则扩容{size_t newcapacity = (0 == ptrheap->capacity) ? 4 : 2 * ptrheap->capacity;HPDataType* tem = (HPDataType*)realloc(ptrheap->arry, newcapacity * sizeof(HPDataType));assert(tem);ptrheap->arry = tem;ptrheap->capacity = newcapacity;}ptrheap->arry[ptrheap->size] = x;			//先尾插一个元素ptrheap->size++;//将尾插的元素进行向上调整以保持堆的数据结构AdjustUp(ptrheap->arry, ptrheap->size - 1); //根据完全二叉树的结构特点可知尾插进数组的元素在二叉树中编号为size-1
}//小堆元素的向下调整接口
void AdjustDown(HPDataType* arry,size_t size,size_t parent)
{assert(arry);size_t child = 2 * parent + 1;   //确定父结点的左孩子的编号while (child < size)			 //child增加到大于或等于size时则调整结束{if (child + 1 < size && arry[child + 1] < arry[child]) //确定左右孩子中较小的孩子结点{++child;}if ( arry[child] < arry[parent])//父结点大于子结点,则子结点需要上调以保持小堆的结构{Swap(arry + parent, arry + child);parent = child;				//将原子结点作为新的父结点继续迭代过程child = 2 * parent + 1;		//继续向下找另外一个子结点}else{break;						//父结点不大于子结点,则堆结构任然成立,无需调整}}
}//删除堆顶元素
void HeapPop(HP* ptrheap)
{assert(ptrheap);Swap(ptrheap->arry, ptrheap->arry + ptrheap->size - 1); //交换堆顶与堆尾元素ptrheap->size--;										//删除堆尾元素AdjustDown(ptrheap->arry, ptrheap->size, 0);			//将堆顶元素进行向下调整以保持堆的数据结构
}

我们只需将小根堆的堆元素上下调整算法接口中的子父结点值大小比较符号改为大于号即可实现大根堆

10.结语

  • 本文的核心:通过堆元素的上下调整算法接口完成堆的构建和删空(并分析过程的时间复杂度)
  • 堆元素上下调整算法接口在后续的堆排序和TopK问题中还会直接用到
  • 堆的高效性来源于如下数学思想:利用指数级展开的数据结构模型实现对数级回溯,从而降低了排序和查找的时间复杂度(不得不说前人的创造真的是无可比拟)

 

 

 

 

 

 

 

相关文章:

数据结构:堆的实现与建堆时间复杂度分析

目录 前言 一.堆的介绍 1.堆的本质 2.堆的分类 二.堆的实现(以小根堆为例) 1.关于二叉树的两组重要结论&#xff1a; 2.堆的物理存储结构框架(动态数组的简单构建) 3. 堆元素插入接口(以小根堆为例) 堆尾元素向上调整的算法接口: 4.堆元素插入接口测试 5.堆元素插入…...

对“车辆销售配置器”的认识与理解

概述 中国汽车市场转为存量阶段后&#xff0c;各车企开始从”以产品为中心“转型到”以客户为中心“&#xff0c;产品的个性化配置需求日益丰富。随着竞争的加剧&#xff0c;车企们不仅要提供出色的产品&#xff0c;而且需要提供更加个性化的产品配置和服务&#xff0c;例如&am…...

Linux编译器——gcc/g++(预处理、编译、汇编、链接)

目录 0.程序实现的两大环境 1.gcc如何完成 预处理 编译 汇编 链接 2.动态库与静态库 对比二者生成的文件大小 3. gcc常用选项 0.程序实现的两大环境 任何一个C程序的实现都要经过翻译环境与执行环境。 在翻译环境中又分为4个部分&#xff0c;预编译、编译、汇编与链…...

Java 操作图片进行缩放旋转翻转加水印

1 纯原生手写图片操作工具类 import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; public class RotateImageUtil {public static BufferedImage rotateImage(BufferedImage bu…...

不能去演唱会现场就多听听耳机里的他们,教你用python来实现一个音乐播放器

前言 最近可以说大麦网很知名了&#xff0c;哈哈还有好多想要用Python来搞抢票脚本的 怎么说呢也不是不行&#xff0c;但是咱今天可不是来搞这个的&#xff0c;我可不抢票&#xff0c;抢了都去不了&#xff0c;上班搞钱啊铁铁们 咱就是说去不了现场&#xff0c;就多听听手机…...

CLion Debug 调试 Makefile 构建的 C 语言程序断点不起作用

最近在研究 jattach&#xff0c;打算在本地调试项目&#xff0c;发现 CLion 可以正常编译运行代码&#xff0c;却无法断点 Debug。由于笔者对 C/C 项目不熟悉&#xff0c;在此记录研究过程中遇到的一些基本问题与解决方法。 文章目录解决方式尝试过的手段【未解决】找 Native D…...

·神经网络

目录11神经网络demo112神经网络demo213神经网络demo320tensorflow2.0 安装教程,所有安装工具&#xff08;神经网络&#xff09;21神经网络-线性回归- demo122神经网络-线性回归- demo228神经网络-多层感知- demo1目录11神经网络demo1 package com.example.xxx; import java.ut…...

【Java 多线程学习】

多线程学习多线程1. 并行与并发2.进程和线程3. *****多线程的实现方式3.1 继承Thread类的方式进行实现3.2 实现Runnable接口方式进行实现3.3 利用Callable和Future接口方式实现3.4 设置获取线程名字4.获得线程对象5.线程休眠6.线程调度[线程的优先级]7.后台线程/守护线程多线程…...

【计算机考研408】快速排序的趟数问题 + PAT 甲级 7-2 The Second Run of Quicksort

前言 该题还未加入PAT甲级题库中&#xff0c;可以通过购买2022年秋季甲级考试进行答题&#xff0c;纯考研题改编 快速排序 常考的知识点 快速排序是基于分治法快速排序是所有内部排序算法中平均性能最优的排序算法快速排序是一种不稳定的排序算法快速排序算法中&#xff0c…...

CSS-Grid(网格)布局

前言 之前HTML 页面的布局基本上都是通过 Flexbox 来实现的&#xff0c;能轻松的解决复杂的 Web 布局。 现在又出现了一个构建 HTML 最佳布局体系的新竞争者。就是强大的CSS Grid 布局。 grid和flex区别是什么&#xff1f;适用什么场景&#xff1f; Flexbox 是一维布局系统&am…...

软件测试4

一 form表单标签 1.form表单标签里面就是所有用户填写的表单数据&#xff1b; action“xxx.py”把表单数据提交给哪一个后台程序去处理 method“post” 传递数据时候的方式方法&#xff0c;post代表隐式提交数据、get明文传送数据 2.input标签的type类型 type“text” 普通的输…...

996的压力下,程序员还有时间做副业吗?

996怎么搞副业&#xff1f; 这个问题其实蛮奇怪的&#xff1a;996的压力下&#xff0c;怎么会还想着搞副业呢&#xff1f; 996还想搞副业的原因有哪些&#xff1f; 大家对于996应该都不陌生&#xff0c;总结就是一个字&#xff1a;忙。 996的工作性质就是加班&#xff0c;就…...

每日学术速递3.1

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Directed Diffusion: Direct Control of Object Placement through Attention Guidance 标题&#xff1a;定向扩散&#xff1a;通过注意力引导直接控制物体放置 作者&#xff1a;…...

金融行业数据模型

一、Teradata FS-LDM Teradata 公司基于金融业务发布的FS-LDM&#xff08;Financial Servies Logical Data Model&#xff09; 十大主题&#xff1a;当事人、产品、协议、事件、资产、财务、机构、地域、营销、渠道。 1、当事人&#xff08;Party&#xff09; 银行所服务的任…...

【面试题】2023前端vue面试题及答案

Vue3.0 为什么要用 proxy&#xff1f;在 Vue2 中&#xff0c; 0bject.defineProperty 会改变原始数据&#xff0c;而 Proxy 是创建对象的虚拟表示&#xff0c;并提供 set 、get 和 deleteProperty 等处理器&#xff0c;这些处理器可在访问或修改原始对象上的属性时进行拦截&…...

(哈希查找)leetcode128. 最长连续序列

文章目录一、题目1、题目描述2、基础框架3、原题链接二、解题报告1、思路分析2、时间复杂度3、代码详解三、本题小知识一、题目 1、题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。…...

js中splice方法和slice方法

splice方法用来操作数组splice(startIndex,deleteNum,item1,....,)此操作会改变原数组。删除数组中元素参数解释&#xff1a;startIndex为起始index索引。deleteNum为从startIndex索引位置开始需要删除的个数。分三种情况&#xff1a;没有传第三个参数的情况下&#xff0c;dele…...

c++ argparse

需求 c程序传参数&#xff0c;像python中argparse一样方便。 方法1 用gflags 参考https://heroacool.blog.csdn.net/?typeblog git clone https://github.com/gflags/gflags cd gflags # 进入项目文件夹 cmake . # 使用 cmake 编译生成 Makefile 文件 make -j 24 # make 编…...

内大892复试真题16年

内大892复试真题16年 1. 输出三个数中较大数2. 求两个数最大公约数与最小公倍数3. 统计字符串中得字符个数4. 输出菱形5. 迭代法求平方根6. 处理字符串(逆序、进制转换)7. 寻找中位数8. 输入十进制输出n进制1. 输出三个数中较大数 问题 代码 #include <iostream>usin…...

面试题 05.02. 二进制数转字符串

二进制数转字符串。给定一个介于0和1之间的实数&#xff08;如0.72&#xff09;&#xff0c;类型为double&#xff0c;打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示&#xff0c;则打印“ERROR”。 示例1: 输入&#xff1a;0.625输出&#xff1a;"0…...

MySQL数据更新操作

文章目录前言添加数据插入数据删除数据修改数据前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 数据更新有两种办法&#xff1a; 1&#xff1a;使用数据可视化工具操作 2&#xff1a;SQL语句 添加数据 前面的添加数据命令一次只能插入一条记录。如果想…...

C# 封装

修正bug之前总是要考虑是什么导致了这个bug&#xff0c;并花些时间了解发生了什么。增加打印输出行的语句可能是一个很有效的调试工具。增加语句来打印诊断信息时&#xff0c;要使用Debug.WriteLine。构造器是CLR第一次创建一个新对象实例时调用的方法。字符串插值会让字符串拼…...

每日学术速递3.2

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Interactive Segmentation as Gaussian Process Classification(CVPR 2023) 标题&#xff1a;作为高斯过程分类的交互式分割 作者&#xff1a;Minghao Zhou, Hong Wang, Qian Zha…...

PCBA方案设计——LCD体重电子秤方案

体重秤&#xff0c;一种测量体重的电子秤&#xff0c;与最近很火的体脂秤来比来说&#xff0c;他是的功能能就有点单一了&#xff0c;只能测量体重&#xff0c;而体脂秤可以精准抓取测量体脂体重等一系列的数据&#xff0c;功能更为多样&#xff0c;但相比之下体重秤的功能简单…...

动态规划--背包问题

动态规划背包问题算法思路代码实现背包问题 假设你要去野营。你有一个容量为6磅的背包&#xff0c;需要决定该携带下面的哪些东西。其中每样东西都有相应的价值&#xff0c;价值越大意味着越重要&#xff1a;  水&#xff08;重3磅&#xff0c;价值10&#xff09;  书&…...

从0开始学python -45

Python3 正则表达式 -3 正则表达式对象 re.RegexObject re.compile() 返回 RegexObject 对象。 re.MatchObject group() 返回被 RE 匹配的字符串。 start() 返回匹配开始的位置end() 返回匹配结束的位置span() 返回一个元组包含匹配 (开始,结束) 的位置 正则表达式修饰符…...

如何用BurpSuite抓取手机数据包

文章目录前言准备工具Burp Suite物理机或虚拟机(移动设备)手机抓包网络环境开启burp并设置代理手机配置代理安装Burp证书开始抓包踩坑后记前言 最近挖了一波src&#xff0c;挖来挖去发现有很多公众号或者app没有测试&#xff0c;这就需要Burp能够抓取手机的数据包了&#xff0…...

Linux性能监控工具iostat解析

1.iostat命令详解 CPU 内存 磁盘 网络 四大子系统 1.1 查看提供iostat命令的软件包 yum provides "*/iostat" yum -y install systatiostat 1 显示实时的数据 iostat 结果自系统启动以来的平均值1.2 iostat命令CPU指标 %user 应用程序消耗CPU资源占比 %nice 进…...

3D可视化大屏制作真的那么难?没有好用的软件解决吗?

有多少人印象里的数据可视化大屏还是像这样的二维大屏&#xff1f;这种二维可视化大屏早就不能满足审美日益提高的大众了。 现在用的都是3D可视化大屏&#xff0c;这种结合了3D技术的可视化形式不仅让数据更加的清晰&#xff0c;也增加了美感&#xff0c;这观看体验&#xff…...

C语言|文件读写,代码运行后留下“记忆”

前言对于一个代码&#xff0c;运行时可能需要保留产生的结果&#xff0c;例如计算值&#xff0c;筛选值&#xff0c;记录点或者小游戏的得分&#xff0c;而正常情况下我们要保存一个数据&#xff0c;想到的肯定是打开我们的文本软件&#xff0c;手撸文字&#xff0c;今天这篇文…...