数据结构 day06

数据结构 day06

  • 6. 双向链表
    • 6.3. 双向循环链表
  • 7. 树 tree
    • 7.1. 特点
      • 7.1.1. 什么是树
      • 7.1.2. 树的特性
      • 7.1.3. 关于树的一些术语
    • 7.2. 二叉树
      • 7.2.1. 什么是二叉树
      • 7.2.2. 二叉树的性质
      • 7.2.3. 满二叉树和完全二叉树的区别
      • 7.2.4. 二叉树的遍历(画图)
      • 7.2.5. 二叉树的顺序存储结构
      • 7.2.6. 二叉树的链式存储结构

6. 双向链表

6.3. 双向循环链表

用双向循环链表实现约瑟夫环

#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
// 定义结构体,一个节点的结构体,一个头尾指针的结构体
typedef struct node
{
	datatype data;
	struct node *prior;
	struct node *next;
}node;
typedef struct double_list
{
	struct node *head;
	struct node *tail;
}list;
// 主函数
int main()
{
	int i = 0;	// 计数
	int all = 0;	// 总人数
	int start = 0;	// 开始报数的人
	int kill = 0;	// 死亡数字
	node *pdel = NULL;	// 用于杀死死者
	node *h = NULL;	// 指向正在报数的人
	node *pnew = NULL:	// 指向新创建的人
	printf("输入总人数,死亡数字,开始报数的人的编号:");
	scanf("%d %d %d", &all, &kill, &start);
	// 创建头尾指针
	list *p = (list *)malloc(sizeof(list));
	if(p == NULL)
	{
		perror("list malloc err");
		return -1;
	}
	// 初始化头尾指针
	p->head = NULL;
	p->tail = NULL;
	// 创建节点
	p->head = (node*)malloc(sizeof(node));
	if(p->head == NULL)
	{
		perror("node malloc err");
		free(p);
		return -1;
	}
	p->tail = p->head;
	// 初始化节点
	p->head->prior = NULL;
	p->head->next = NULL;
	p->head->data = 1;
	// 循环创建所有的人
	for(i = 2; i <= all; i++)
	{
		pnew = (node*)malloc(sizeof(node));
		if(pnew == NULL)
		{
			perror("pnewnode malloc err!!");
			return -1;
		}
		// 初始化pnew
		pnew->next = NULL;
		pnew->prior = NULL;
		pnew->data = i;
		// 建立链接
		pnew->prior = p->tail;
		p->tail->next = pnew;
		// 移动尾指针
		p->tail = p->tail->next;
	}
	// 首尾相连
	p->tail->next = p->head;
	p->head->prior = p->tail;
	// h指向开始报数的人
	h = p->head;
	while(h->data != start)
		h = h->next;
	// 开始报数,报到死亡数字之后杀人
	while(h != h->next)
	{
		for(i = 1; i <= kill; i++)
		{
			h = h->next;
		}
		pdel = h;
		h = h->next;
		printf("kill %d\n", pdel->data);
		// 杀死pdel
		pdel->prior->next = pdel->next;
		pdel->next->prior = pdel->prior;
		free(pdel);
		pdel = NULL;
	}
	printf("Survivor is %d", h->data);
	// 释放h
	free(h);
	h = NULL;
}

7. 树 tree

7.1. 特点

7.1.1. 什么是树

  1. 存在一个根节点(root)
  2. 其余节点可以分为若干子树

7.1.2. 树的特性

  1. 层次关系,一对多,
  2. 每个节点最多只有一个前驱,根节点无前驱
  3. 每个节点可以有多个后继,叶节点无后继

7.1.3. 关于树的一些术语

  1. 度数:节点的子树个数,节点有几个孩子
  2. 树度数:整个树中节点最大的度数
  3. 叶节点或终端节点,度数为0的节点,最末端的节点
  4. 分支节点:度数不为0,有孩子的节点
  5. 内部节点:除根节点以外的分支节点
  6. 节点层次:根节点到叶节点之间的个数,称为层数,根节点的层数是1
  7. 树的深度又叫树的高度:最大的节点层次

7.2. 二叉树

7.2.1. 什么是二叉树

每个节点最多只有两个孩子,分为左孩子和右孩子。由一个根节点和两个互不相交的左子树和右子树组成。二叉树严格区分左右孩子,哪怕只有一个孩子也要分左右。

7.2.2. 二叉树的性质

  1. 二叉树第k层上的节点最多有2k-1
  2. 深度为k的二叉树最多有2k-1个节点
  3. 叶节点的数量比度数为2的节点的数量多1
    计算
    度数为0:n0
    总节点数为各类节点之和:n = n0 + n1 + n2
    总节点数为所有子节点数加一:n = 1n1 + 2n2 + 1
    0 = n2 + 1 - n0
    n0 = n2 + 1

7.2.3. 满二叉树和完全二叉树的区别

满二叉树:深度为k时节点为2k-1
完全二叉树:只有最下面两层有度数小于2的节点,最下面一层的叶节点都是左孩子,那么就是完全二叉树
非完全二叉树:两种情况:

  1. 除最下面两层外还有别的地方有度数不为2的二叉树
  2. 只有最下面两层有度数不为2的二叉树,最下面一层存在右孩子

7.2.4. 二叉树的遍历(画图)

前序:根左右,先找根,再找左孩子
中序:左根右,先找左孩子,再找根,再找右孩子
后序:左右根
前序
每个节点左边画圈,沿着最左边划线,沿线顺序就是前序的遍历顺序

中序

后序

练习:
已知遍历结果如下,试画出对应的二叉树。
前序: A B C E H F I J D G K
中序: A H E C I F J B D K G
提示:用前序确定根节点,然后用中序找到根节点然后再找左右子。
在这里插入图片描述

7.2.5. 二叉树的顺序存储结构

完全二叉树的节点编号方法为从上到下,从左到右,根节点为1号节点
公式:完全二叉树的节点数为n,某节点编号为i

  1. 当 i > 1 (不为根节点)时,有父节点。父节点编号为i/2;
  2. 当2i <= n时,有左孩子,其编号为2i, 否则没有左孩子,是叶节点
  3. 当 2i <= n 时,有右孩子,其编号为 2i + 1,否则没有右孩子

n个节点可以用n+1个元素的数组顺序存储,节点号和数组下标一一对应,下标为0的位置不用,非完全二叉树虚构节点组成完全二叉树之后存储,会造成空间的浪费

7.2.6. 二叉树的链式存储结构

用链表实现,基于完全二叉树规律创建二叉树,按照完全二叉树的编号方法,从上到下,从左到右

1. 头文件 tree.h

#ifndef __TREE_H__
#define __TREE_H__

typedef struct tree_t
{
	int data;
	int id;
	tree_t* lchild;
	tree_t* rchild;
}tree;

// 1. 创建二叉树
tree* CreateBitTree(int n, int i);
// 2. 前序遍历
void PreOrder(tree* p);
// 3. 中序遍历
void InOrder(tree* p);
// 4. 后序遍历
void PostOrder(tree* p);
#endif
  1. 创建二叉树,用递归函数创建。
tree* p CreateBitTree(int n, int i) //i根节点的编号,n:节点数
{
	// 申请空间存放根节点
	tree* p = (tree*)malloc(sizeof(tree));
	// 容错判断
	if(p == NULL)
	{
		perror("BitTree malloc err!!");
		return NULL;
	}
	
	// 初始化
	p->id = i;
	p->data = i;
	if(2*i <= n)
		p->lchild = CreateBitTree(n, 2*i);
	else
		p->lchild = NULL;
	if(2*i+1 <= n)
		p->rchild = CreateBitTree(n, 2*i+1);
	else
		p->rchild = NULL;
	
	return p;
}
  1. 正序遍历二叉树,根左右
void PreOrder(tree* p)
{
	if(p == NULL)
		return;
	// 根节点输出
	printf("%-4d", p->data);
	
	// 查看左孩子
	if(p->lchild != NULL)
		PreOrder(p->lchild);
	
	// 查看右孩子
	if(p->rchild != NULL)
		PreOrder(p->rchild);
}
  1. 中序遍历,左根右
void InOrder(tree* p)
{
	if(p == NULL)
		return;
	if(p->lchild != NULL)
		InOrder(p->lchild);
	printf("%-4d", p->data);
	if(p->rchild != NULL)
		InOrder(p->rchild);
}
  1. 后序遍历,左右根
void PostOrder(tree* p)
{
	if(p->lchild !=  NULL)
		PostOrder(p->lchild);
	if(p->rchild != NULL)
		PostOrder(p->rchild);
	printf("%-4d", p->data);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机械学习基础-5.分类-数据建模与机械智能课程自留

data modeling and machine intelligence - CLASSIFICATION 为什么我们不将回归技术用于分类&#xff1f;贝叶斯分类器&#xff08;The Bayes Classifier&#xff09;逻辑回归&#xff08;Logistic Regression&#xff09;对逻辑回归的更多直观理解逻辑 /sigmoid 函数的导数我们…

音频进阶学习十三——Z变换二(有理z变换、稳定性与反变换)

文章目录 前言一、有理Z变换1.定义2.作用3.LTI系统的传递函数1&#xff09;传递函数的定义2&#xff09;差分方程转换传递函数 二、极点和零点1.有理分式的极点和零点2.稳定性实例 二、逆Z变换1.观察法2.部分分式展开法1&#xff09;定义2&#xff09;举例 3.幂级数法/长除法1&…

centos部署open-webui

提示&#xff1a;本文将简要介绍一下在linux下open-webui的安装过程,安装中未使用虚拟环境。 文章目录 一、open-webui是什么&#xff1f;二、安装流程1.openssl升级2.Python3.11安装3.sqlite安装升级4.pip 下载安装open-webui 总结 一、open-webui是什么&#xff1f; Open W…

DeepSeek R1 32B 本地部署实战

#DeepSeek# DeepSeek是一款基于人工智能的智能助手&#xff0c;专为提升工作效率和信息获取能力而设计。它结合了自然语言处理、机器学习和大数据技术&#xff0c;能够快速理解用户需求并提供精准的答案或解决方案。 DeepSeek的核心功能 智能问答 DeepSeek可以回答各种问题&…

day09_实时类标签/指标

文章目录 day09_实时类标签/指标一、日志数据实时采集2、Flume简介2.3 项目日志数据采集Flume配置2.3.1 涉及的Flume组件和参数2.3.2 Nginx日志采集2.3.3 用户行为日志采集 二、Nginx日志数据统计1、日志格式说明2、数据ETL2.1 日志抽取2.1.1 正则表达式2.1.2 基于Spark实现Ngi…

硬件学习笔记--41 电磁兼容试验-5 射频场感应的传导干扰试验介绍

目录 电磁兼容试验-射频场感应的传导干扰试验介绍 1.试验目的 2.试验方法 3.判定依据及意义 电磁兼容试验-射频场感应的传导干扰试验介绍 驻留时间是在规定频率下影响量施加的持续时间。被试设备&#xff08;EUT&#xff09;在经受扫频频带的电磁影响量或电磁干扰的情况下&a…

告别卡关!XSS挑战之旅全关卡通关思路详解

XSS挑战之旅 XSS测试思路Level1Level2Level3Level4Level5Level6Level7Level8Level9Level10Level11Level12Level13Level14Level15Level16Level17Level18Level19Level20免责声明&#xff1a; XSS测试思路 确定输入输出点&#xff1a; 寻找URL参数、表单输入、HTTP头&#xff08;R…

连锁企业管理系统的五大核心功能

连锁管理系统对于连锁企业的运营和发展至关重要&#xff0c;以下以核货宝连锁管理系统为例&#xff0c;介绍其五大核心功能&#xff1a; 门店管理功能 门店信息管理&#xff1a;核货宝连锁管理系统可集中管理所有门店的详细信息&#xff0c;包括门店地址、联系方式、营业时间、…

【第12章:深度学习与伦理、隐私—12.4 深度学习与伦理、隐私领域的未来挑战与应对策略】

凌晨三点的自动驾驶测试场,AI系统突然在暴雨中做出惊人决策——它选择撞向隔离带而不是紧急变道,因为算法推演发现隔离带后的应急车道站着五个工程师。这个惊悚的伦理困境,揭开了深度学习伦理危机最尖锐的冰山一角。 一、潘多拉魔盒已开:深度学习伦理的四大原罪 1.1 数据原…

深度学习(1)-简单神经网络示例

我们来看一个神经网络的具体实例&#xff1a;使用Python的Keras库来学习手写数字分类。在这个例子中&#xff0c;我们要解决的问题是&#xff0c;将手写数字的灰度图像&#xff08;28像素28像素&#xff09;划分到10个类别中&#xff08;从0到9&#xff09;​。我们将使用MNIST…

腿足机器人之八- 腿足机器人动力学

腿足机器人之八- 腿足机器人动力学 刚体动力学接触动力学与地面交互稳定性判据ZMP(零力矩点)CoM(Center of Mass)捕获点 简化动力学模型双足机器人走路与小跑的动力学对比挑战与前沿技术 腿足机器人的运动学解决“如何到达目标位置”的问题&#xff0c;动力学解决“如何高效稳定…

Kubernetes控制平面组件:etcd高可用集群搭建

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;Kubernetes控…

HCIA项目实践--静态路由的拓展配置

7.7 静态路由的拓展配置 网络中的两个重要思想&#xff1a; &#xff08;1&#xff09; 实的不行来虚的&#xff1b; &#xff08;2&#xff09; 范围太大&#xff0c;划分范围。&#xff08;分治&#xff09; 7.7.1 负载均衡 &#xff08;1&#xff09;定义 负载均衡是一种网…

node.js + html调用ChatGPTApi实现Ai网站demo(带源码)

文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言 关注博主&#xff0c;学习每天一个小demo 今天是Ai对话网站 又到了每天一个小demo的时候咯&#xff0c;前面我写了多人实时对话demo、和视频转换demo&#xff0c;今天…

类和对象(5)——抽象类和接口

目录 1. 抽象类 1.1 抽象类的概念 1.2 抽象类语法&#xff1a;abstract关键字 1.3 抽象类的特性 1.4 抽象类的作用 2. 接口 2.1 接口的概念 2.2 接口语法&#xff1a;interface关键字 2.3 接口的实现&#xff1a;implements关键字 2.4 接口的特性 2.5 实现多个接口 …

kubectl exec 实现的原理

kubectl exec 是 Kubernetes 提供的一个命令&#xff0c;它允许你在指定的 Pod 中执行命令&#xff0c;类似于在容器中打开一个终端会话。这个功能对于调试、监控和管理容器化应用非常有用。kubectl exec 的实现涉及到多个 Kubernetes 组件和机制&#xff0c;包括 API Server、…

【ubuntu24.04】 强制重启导致大模型的磁盘挂载出错

挂载NTFS文件系统出错 各种模型放在了这个机械硬盘上&#xff0c;虽然速度慢&#xff0c;但是好在容量大。大模型在工作&#xff0c;但是程序看起来有问题&#xff0c;导致系统卡死了&#xff0c;然后我重启了&#xff0c;然后报错&#xff1a;wrong fs type bad option &…

【数据结构】 栈和队列

在计算机科学的世界里&#xff0c;数据结构是构建高效算法的基础。栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;作为两种基本且重要的数据结构&#xff0c;在软件开发、算法设计等众多领域都有着广泛的应用。今天&#xff0c;我们就来深入探讨一下栈和…

移动端测试的挑战与解决方案:兼容性、网络问题及实战策略

引言 移动应用已成为用户触达服务的核心入口,但移动端测试面临设备多样性、网络波动、用户场景复杂等多重挑战。据Statista统计,2023年全球活跃移动设备超180亿台,操作系统(Android/iOS)版本碎片化率超30%,这对测试工程师提出了极高要求。本文深度解析移动端测试的核心痛…

【设计模式】03-理解常见设计模式-行为型模式(专栏完结)

前言 前面我们介绍完创建型模式和创建型模式&#xff0c;这篇介绍最后的行为型模式&#xff0c;也是【设计模式】专栏的最后一篇。 一、概述 行为型模式主要用于处理对象之间的交互和职责分配&#xff0c;以实现更灵活的行为和更好的协作。 二、常见的行为型模式 1、观察者模…