数据结构常见算法总结

图的广度遍历
  1. 初始化visited[]数组
  2. for 对未访问过的顶点调用广度优先遍历算法
  3. 广度优先遍历
    1. 先将参数送进来的序号对应的visited[v]置为true,并将v入队
    2. 队列Q不空时循环:遍历Q中元素,并将未访问过的边表结点入队
bool visited[max_vex_num];
void BFSTraverse(Graph G){//初始化访问数组for(int i = 0; i< G.vexnum; i++)visited[i] = false;//广度遍历每个未访问过的节点for(int v = 0; v < G.vexnum; v++)if(!visited[v])BFS(G,v);
}void BFS(Graph G, int v){int p;int Q[G.vexnum];int front = 0, rear = 0;//先访问进来的节点,并入队visit(v);visited[v] = true;Q[rear++] = v;while(front != rear){p = Q[front++];for(int w = FirstNeighbor(G,p); w>=0; w = NextNeighbor(G,p,w)){//访问未被访问过的边表节点,并入队if(!visited[w]){visit(w);visited[w] = true;Q[rear++] = w;}}}
}
深度优先遍历:递归实现

只要是没访问节点都直接进行深度遍历

bool visited[max_vex_num];
void DFSTraverse(Graph G){for(int i = 0; i < G.vexnum; i++)visited[i] = false;for(int v = 0; v < G.vexnum; v++){if(!visited[v])DFS(G,v);}
}//递归实现
void DFS(Graph G, int v){visit(v);visited[v] = true;//对每个边表结点都进行深度遍历for(int w = FirstNeighbor(G,v); w>=0; w = NextNeighbor(G,v,w)){if(!visited[w])DFS(G,w);}
}
深度优先遍历:非队列实现

从顶点v开始进行深度优先搜索,一次遍历一个连通分量,由于是出栈的时候再访问所以得到的遍历顺序是从边表结点的右到左的次序。

  1. 根节点入栈,栈不空时循环;
  2. 栈顶元素出栈并访问,将栈顶元素所有未入栈的边表结点入栈
bool ispushed[MaxSize]; 		//标记顶点是否入栈过,防止重复入栈
void DFS_Non_RC(Graph G, int v){InitStack(S);for(int i = 0; i < G.vexnum; i++)ispushed[i] = false;Push(S,v);	//入栈ispushed[v] = true;	//标记,防止再次入栈while(!IsEmpty(S)){//出栈并访问int k = Pop(S);visit(k);//将k节点的所有未入栈的边表结点入栈for(int w = FirstNeighbor(G,k); w>=0; w = NextNeighbor(G,k,w)){if(!ispushed[w]){Push(S,w);ispushed[w]=true;}}}
}
BFS算法求单源最短路径(无权图)
bool visited[MaxSize];	//访问数组
int d[MaxSize];		//保存u到i的路径长度
void BFS_Distance(Graph G, int u){int Queue[G.vexnum];int front = 0, rear = 0;//初始化数组for(int i=0; i<G.vexnum; i++){visited[i] = false;d[i] = -1;}//初始化根节点d[u] = 0;visited[u] = true;Quere[rear++] = u;int x;while(front != rear){x = Queue[front++];for(int w = FirstNeighbor(G,x); w>=0; w = NextNeighbor(G,x,w)){if(!visited[w]){d[w] = d[u] + 1;	//路径长度+1visited[w] = true;Queue[rear++] = w;}}}
}
树的先序、中序遍历

先序:沿着根节点的左孩子,依次入栈并访问,直到孩子为空;将栈顶元素出栈,并开始遍历右子树

中序:沿着根节点的左孩子,依次入栈,直到孩子为空,将栈顶元素出栈并访问,并开始遍历右子树

void Order(BiTree T){BiNode *Stack[MaxSize];		//声明一个栈int top = -1;BiNode *p = T;//栈未空或树未遍历完while(top != -1 || p != NULL){if(p){visit(p);		//访问节点,先序遍历Stack[++top] = p;	//入栈p = p->lchild;}else{p = Stack[top--];//visit(p);			//在这里访问就是中序遍历p = p->rchild;}}
}
树的后序遍历
双栈法
  1. 将根节点入栈S1;
  2. S1栈顶元素p出栈,放入栈S2,并将栈顶元素p的左右子树入栈S1;
  3. 重复操作2,直到S1栈空。
  4. S2中的元素依次出栈得到的就是后序遍历的结果。
void Post_Order(BiTree T){if(!T) return;BiNode *S1[MaxSize], *S2[MaxSize];int top1 = -1, top2 = -1;BiNode *p;S1[++top1] = T;		//根节点入栈S1while(top1 != -1){p = S1[top1--];S2[++top2] = p;		//S1的栈顶元素移入S2if(p->lchild)S1[++top1] = p->lchild;		//左孩子入栈S1if(p->rchild)S1[++top1] = p->rchild;		//右孩子入栈S2}//S2中的结果出栈while(top2 != -1){p = S2[top--];visit(p);}
}
单栈标记法
  1. 从根节点开始,左孩子依次入栈,直到左孩子为空;

  2. 栈顶元素出栈,并判断栈顶元素是否有未被访问的右孩子

    ①有右孩子,且没有访问过,则将栈顶元素重新入栈,并遍历右子树

    ②如果没有右孩子,或者右孩子已经被访问过,则直接访问栈顶元素。

void Post_Order(BiTree T){BiNode *S[MaxSize];int top = -1;BiNode *p = T, *r = NULL;	//r指向最近访问的节点//栈未空 或 树未遍历完while(top != -1 || p != NULL){if(p){S[++top] = p;	//入栈p = p->lchild;	//遍历左子树}else{p = S[top--];if(p->rchild != NULL && p->rchild != r){//有未被访问的有孩子S[++top] = p;	//重新入栈p = p->rchild;	//遍历右子树}else{visit(p);	//访问节点r = p;		//标记节点为最近访问过p = NULL;}}}
}
层次遍历

借助队列,先将根节点依次入队,出队并将其左右节点(若存在)依次入队,重复上述操作,直到队空

void Level_order(BiTree T){if(T == NULL) return;BiNode *Queue[MaxSize];int front = 0, rear = 0;BiNode *p = NULL;Queue[rear++] = T;while(front < rear){p = Queue[front++];visit(p);if(p->lchild!=NULL)Queue[rear++] = p->lchild;if(p->rchild!=NULL)Queue[rear++] = p->rchild;}
}
求二叉树的层数、高度
非递归:层序遍历+记录每层最后一个节点

也可以求节点所在层数

借助队列对二叉树进行层次遍历,当每层的最后一个节点的左右子树(若存在)入队之后,记录队尾结点rear的位置,即为下一层的最后一个节点,并将树的层数+1

int TreeLevel(BiTree T){if(T == NULL)return 0;int level, flag;BiNode *Queue[MaxSize];int front = 0, rear = 0;BiNode *p;Queue[rear++] = T;flag = rear; 	//标记队尾结点while(front != rear){p = Queue[front++];/**找到所求节点,直接返回层数if(p == x) return leval+1;*/if(p->lchild!=NULL)Queue[rear++] = p->lchild;if(p->rchild!=NULL)Queue[rear++] = p->rchild;if(front == flag){flag = rear;	//标记队尾结点level++;}}return level;
}
递归
int TreeLevel(BiNode T){if(T == NULL)return 0;int left = TreeLevel(T->lchild);int right = TreeLevel(T->rchild);if(left > right)return left + 1;elsereturn right + 1;
}
输出最长路径上的节点

对二叉树进行后序遍历,用到辅助栈S1,再用一个栈S2来存放最长路径上的节点,用visited指针标记最近访问的节点

  1. 从根节点开始,左孩子依次入栈,直到左孩子为空;

  2. 栈顶元素出栈,并判断栈顶元素是否有未被访问的右孩子

    ①有右孩子,且没有访问过,则将栈顶元素重新入栈,并遍历右子树

    ②没有右孩子,或者右孩子已经被访问过

    ​ a. 是否是叶子节点?

    ​ 若是→比较S1与S2的栈顶指针top1和top2,如果top1>top2,说明S1中的路径长度更长,因此用该路径替换S2的内容;

    ​ b. 访问栈顶元素,visited = p;

  3. 继续遍历,直到S1为空,最后S2中的元素出栈,就是从根节点到叶节点的最长路径。

void longestRoute(BiTree T) {BiNode *S1[MAXSIZE], *S2[MAXSIZE];int top1 = -1, top2 = -1;BiNode *p = T, *visited = NULL;while(top1 != -1 || p != NULL){if(p!=NULL){S1[++top1] = p;p = p->next;	//遍历左子树}else{p = S1[top1--];//当p有未被访问过的右孩子if(p->rchild != NULL && visited != p->rchild){S1[++top1] = p;p = p->rchild;	//遍历右子树}else{//当p是叶节点if(p->lchild==NULL&&p->rchild==NULL){if(top1 > top2){for(int i = top1; i>=0; i--)S2[i] = S1[i];top2 = top1;}}visited = p;	//标记最近访问的节点p = NULL;}}}while(top2 != -1){p = S2[top2--];print(p);}
}
求树的宽度
非递归:层次遍历+计算每行宽度

在求二叉树层数的非递归层数的基础上,在遍历每一行最后一个元素的时候,都计算下一行的节点个数:count=rear-front

int TreeWidth(BiTree T){if(T == NULL)return 0;int flag;BiNode *Queue[MaxSize];int front = 0, rear = 0;BiNode *p;int count = 0, width = 0;	//count表示下一行的节点个数,width表示树的宽度Queue[rear++] = T;flag = rear; 	//标记队尾结点while(front != rear){p = Queue[front++];if(p->lchild!=NULL)Queue[rear++] = p->lchild;if(p->rchild!=NULL)Queue[rear++] = p->rchild;//已经出队到这一行的最后一个元素if(front == flag){flag = rear;	//更新队尾结点标记count = rear - front;	//计算下一行节点个数if(count > width)width = count;}}return width;
}
交换二叉树左右子树

非递归:层次遍历,将入队次序改为先右后左

递归:

void swap(BiTree T){BiNode *q;q = T->lchild;T->lchild = T->rchild;T->rchild = q;swap(T->lchild);swap(T->rchild);
}
求叶子结点个数

若节点为空,则返回0,若节点为叶子结点则返回1,否则返回左、右子树叶子结点的和,递归调用。

int Degree(BiTree T){if(!T) return 0;if(T->lchild == NULL && T->rchild == NULL)return 1;return degree(T->lchild) + degree(T->rchild);
}
找p与q的最近公共祖先,求祖先都用后序遍历
  1. 使用单栈标记法的后序遍历,栈S1用于后序遍历;
  2. 当遍历到p或q中的任意一个时,将S1中的元素复制到S2中;
  3. 继续找另一个,找到后退出循环。
  4. 遍历S1与S2,从栈底开始,找到第一个不同的点,返回该点的前驱结点。算法结束
void SearchParents(BiTree T, BiNode *p, BiNode *q){BiNode *S1[MaxSize], *S2[MaxSize];int top1 = -1, top2 = -1;BiNode *r = T, *visited = NULL;int flag = 0; 	//标记是否已经找到一个节点int i;while(top1 != -1 && r != NULL){if(r){if(r == p ||r == q){//找到其中一个if(flag == 0){for(int i = 1; i<=top1; i++)S2[i] = S1[i];top2 = top1;flag = 1;}else{//p和q都找到了退出循环break;}}S1[++top1] = r;		//入栈r = r->lchild;		//遍历左子树}else{r = S1[top1--];//如果有未被访问过的右子树if(r->rchild != NULL && visited != r){S1[++top1] = r;r = r->rchild;}else{visited = r;r = NULL;}}}//p和q都找到了for(i=0; S1[i] == S2[i] && i<=top1 && i <= top2; i++);	//从栈底开始,找到第一个不相等的节点return S1[i-1];		//返回该节点的前驱
}

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

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

相关文章

React学习计划-React16--React基础(七)redux使用与介绍

笔记gitee地址 一、redux是什么 redux是一个专门用于做状态管理的js库&#xff08;不是react插件库&#xff09;它可以用在react、angular、vue的项目中&#xff0c;但基本与react配合使用作用&#xff1a;集中式管理react应用中多个组件共享的状态 二、什么情况下需要使用r…

sheng的学习笔记-卷积神经网络

源自吴恩达的深度学习课程&#xff0c;仅用于笔记&#xff0c;便于自行复习 导论 1&#xff09;什么是卷积神经网络 卷积神经网络&#xff0c;也就是convolutional neural networks &#xff08;简称CNN&#xff09;&#xff0c;使用卷积算法的神经网络&#xff0c;常用于计…

感染了后缀为.[sqlback@memeware.net].2700勒索病毒如何应对?数据能够恢复吗?

导言&#xff1a; 近期&#xff0c;[sqlbackmemeware.net].2700 勒索病毒成为网络安全的一大威胁。该勒索病毒采用高度复杂的加密算法&#xff0c;将用户文件加密并勒索赎金。了解该病毒的特征对于有效恢复被加密数据以及预防进一步感染至关重要。如果受感染的数据确实有恢复的…

Ubuntu Desktop 软件包管理

Ubuntu Desktop 软件包管理 ubuntu desktop 常见的包格式有 deb, AppImage, snap 等。本文介绍这几种格式软件的安装方法。 1.deb 格式 使用 apt 命令管理 deb 包 详细查看 man apt。 apt是一个命令行程序&#xff0c;用于在Ubuntu&#xff0c;Debian和基于Debian的Linux发…

linux 网络工具(一)

linux 网络工具 1. nmcli命令1.1 介绍1.2 networking 网络控制1.3 connection 连接管理1.4 device 设备管理1.5 nmcli 返回状态码 2. ifcfg命令家族2.1 ifconfig2.2 route2.3 netstat 3. 静态路由CentosUbuntu - netplanUbuntu - network-manager 1. nmcli命令 1.1 介绍 RHEL…

Vue - 计算属性的妙用

计算属性的运用 Vue 组件的计算属性是一种通过对已有数据进行实时计算&#xff0c;生成新的数据的方式。在下面的代码中&#xff0c;我们通过计算属性 publishedBooksMessage 实时展示作者发布的书籍信息。 <template><div><p>作者: {{ author.name }}<…

工具系列:TimeGPT_(6)同时预测多个时间序列

TimeGPT提供了一个强大的多系列预测解决方案&#xff0c;它涉及同时分析多个数据系列&#xff0c;而不是单个系列。该工具可以使用广泛的系列进行微调&#xff0c;使您能够根据自己的特定需求或任务来定制模型。 # Import the colab_badge module from the nixtlats.utils pac…

ubuntu 使用openssl制作一个自签名证书

我们需要为浏览器创建自己的根CA证书来信任自签名证书。因此&#xff0c;让我们首先创建根CA证书 创建根CA证书 创建文件夹 mkdir openssl && cd openssl执行以下openssl命令&#xff0c;生成 rootCA.key 以及 rootCA.crt. 用你的域名或者ip地址替换demo.mlopshub.c…

如何将自己的项目上传到github上,并进行项目管理

将项目上传到GitHub并进行项目管理是一个多步骤的过程。以下是一个简单的示例&#xff0c;指导您如何完成这一过程&#xff1a; 1. 创建GitHub账户 如果您还没有GitHub账户&#xff0c;请先在 GitHub 上注册一个。 2. 创建新仓库 登录您的GitHub账户。在GitHub主页的右上角…

HTML简介、基本骨架、标签的关系、注释、路径

1 HTML HTML超文本标记语言 超文本——链接 标记——标记也叫标签&#xff0c;带尖括号<>的文本 标签语法&#xff1a; 标签成对出现&#xff0c;中间包裹内容 <>里面放英文字母(标签名) 结束标签比开始标签多/ 拓展&#xff1a; 双标签&#xff1a;成对出现的标签…

编程语言的未来

当我们思考编程语言的未来时&#xff0c;我们不能忽视JavaScript的重要性。作为前端开发者&#xff0c;我们深知JavaScript在开发中的重要性。它不仅改变了我们与网页的交互方式&#xff0c;还推动了整个前端开发领域的发展。 那么&#xff0c;从当前的趋势和技术发展来看&…

HarmonyOS —— UIAbility 页面跳转总结

HarmonyOS —— UIAbility 页面跳转总结 Author&#xff1a;Gorit Date&#xff1a;2023年12月27日 一、系统环境 HarmonOS API9SDK 3.1.0Stage 模型 二、应用内跳转 在应用内之前实现不同 page 的跳转&#xff0c;我们使用 router 即可&#xff0c;页面跳转主要支持如下…

Python:PyTorch

简介 PyTorch是一个开源的机器学习库&#xff0c;由Facebook的人工智能研究团队&#xff08;FAIR&#xff09;开发&#xff0c;用于应用于机器学习和深度学习的Python程序。PyTorch基于Torch&#xff0c;使用Python语言重新编写&#xff0c;使得它更容易使用和扩展。它支持强大…

生产系统稳定上线600天!中国联通CUDB for OceanBase的开源共建和规模化应用

中国联通软件研究院架构部平台承载了上千应用的数据库需求&#xff0c;并且现存大量数据库使用过程缺少规范、缺少监控&#xff0c;同时还存在着数据库核心技术相关风险。为了实现核心技术自主可控&#xff0c;及时为用户解决线上问题、满足用户的功能需求&#xff0c;提供物美…

gnu工程的编译 - 以libiconv为例

文章目录 gnu工程的编译 - 以libiconv为例概述gnu官方源码包的发布版从官方的代码库直接迁出的git版源码如果安装了360, 需要添加开发相关的目录到信任区生成 configrue 的方法备注END gnu工程的编译 - 以libiconv为例 概述 gnu工程的下载分2种: gnu官方源码包的发布版 这种…

Global Mapper SDK 19 中文开发文档(八)

7.2.8 GM_DBUtil &#xff08;1&#xff09;声明 public static class GM_DBUtil &#xff08;2&#xff09;方法 方法描述DBGetTableList获取指定空间数据库中的表列表DBIsDatabaseFile指示输入文件是否为数据库&#xff08;Esri地理数据库、Spatialite等&#xff09;DBMa…

gitee+picgo+typora图床搭建

giteepicgotypora图床搭建 1.安装typora 官网下载直接安装&#xff1a;https://www.typora.io/#download 2.编辑typora图像设置 打开 文件 -> 偏好设置 -> 图像设置 插入图片时 选择 上传图片设置 上传服务 为 PicGo-Core(command line) 3.为typora安装PicGo-Core 点…

vue 父页面监听子页面值的变化

在Vue中&#xff0c;可以通过使用$emit()来触发事件并传递数据。 首先&#xff0c;需要在父组件中定义一个自定义事件名称&#xff0c;然后将该事件与相应的处理函数关联起来。当子组件改变了其值时&#xff0c;就会调用这个处理函数。 下面是一个示例代码&#xff1a; <…

达梦dm.ini参数之SELECT_LOCK_MODE详解

一、背景 1.现象概述 某项目当晚分区表变更&#xff0c;因为manager工具多开了1个窗口执行了语句慢取消了&#xff0c;新开了一个会话窗口执行添加分区/删除分区/truncate分区卡死了&#xff0c;v$session查不到关于这张分区表的阻塞和事务&#xff0c;但是在v$lock里根据表的…

DRF(Django Rest Framework)框架基于restAPI协议规范的知识点总结

Django Rest Framework学习 一、初识DRF组件 1.1 FBV和CBV FBV&#xff1a;function based view from django.shortcuts import render, HttpResponse # 这种是基于FBV模式 函数模式实现Views函数 def login(request):if request.method GET:return HttpResponse("Get…