首页 > 其他分享 >根据一个数组,创建一个Segment Tree(线段树)

根据一个数组,创建一个Segment Tree(线段树)

时间:2023-09-27 19:56:29浏览次数:42  
标签:Queue 线段 Tree TNode queue NULL Segment void

线段树的特点

线段树的优势

线段树的构造过程

(0,5)37:数组元素下标0~5的元素之和是37
(0,2)21:数组元素下标0~2的元素之和是21

线段树的基本数据结构(结点结构由五个分量组成)

运行结果

(C语言代码)递归的创建一颗线段树,然后中序、先序、后序遍历这个结点

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct TNode{
	/*线段树的结点结构*/
	int lidx, ridx;
	struct TNode *left, *right;
	int sum;
} TNode, *SegmentTree;

typedef struct QNode{
	/*队列的结点结构,队列用于层序遍历线段树*/
	TNode* ptr2TNode;
	struct QNode *next;
} QNode, *Queue;

SegmentTree build(int* arr, int l, int r);
void inOrder(SegmentTree T);
void preOrder(SegmentTree T);
void postOrder(SegmentTree T);
void levelOrder(SegmentTree T, Queue queue);
void visit(TNode* Node);
Queue initQueue();
TNode* delete(Queue queue);
void add(Queue queue, TNode* Node);
bool isEmpty(Queue queue);

int main(int argc, char* argv[]) {
	int arr[] = {8, 4, 9, 11, 3, 2};
	SegmentTree SegTree = build(arr, 0, 5);
	
	/*中序遍历线段树*/
	printf("InOrder   : ");
	inOrder(SegTree);
	printf("\n");

	/*先序遍历线段树*/
	printf("PreOrder  : ");
	preOrder(SegTree);
	printf("\n");

	/*后序遍历线段树*/
	printf("PostOrder : ");
	postOrder(SegTree);
	printf("\n");

	/*层序遍历线段树*/
	printf("LevelOrder: ");
	Queue queue = initQueue();
	levelOrder(SegTree, queue);

	return 0;
}

SegmentTree build(int* arr, int l, int r) {
    /*创建一颗线段树*/
	TNode* T = (TNode*)malloc(sizeof(TNode));
	T->lidx = l, T->ridx = r;
    /*叶子节点的left和right指针都是空
      叶子结点的sum域对应于数组的元素
      非叶子节点的left和right指针需要递归创建
      非叶子节点的sum域等于左右孩子的sum域之和
    */
	if (l < r) {
		T->left = build(arr, l, (l+r)/2);
		T->right = build(arr, (l+r)/2 + 1, r);
		T->sum = T->left->sum + T->right->sum;
	} else if(l == r) {
		T->left = NULL, T->right = NULL;
		T->sum = arr[l];
	}
	return T;
}

void inOrder(SegmentTree T) {
    /*先序遍历线段树*/
	if (T != NULL) {
		inOrder(T->left);
		visit(T);
		inOrder(T->right);
	}
}

void visit(TNode* Node) {
    /*访问线段树的结点*/
	printf("%2d ", Node->sum);
}

void preOrder(SegmentTree T) {
    /*先序遍历线段树*/
	if (T != NULL) {
		visit(T);
		preOrder(T->left);
		preOrder(T->right);
	}
}
void postOrder(SegmentTree T) {
    /*后序遍历线段树*/
	if (T != NULL) {
		postOrder(T->left);
		postOrder(T->right);
		visit(T);
	}	
}

Queue initQueue() {
    /*初始化一个空队列*/
	Queue q = (Queue)malloc(sizeof(QNode));
	q->ptr2TNode = NULL;
	q->next = NULL;
	return q;
}

TNode* delete(Queue queue) {
    /*队头元素出队*/
	if (!isEmpty(queue)) {
		QNode* temp = queue->next;
		queue->next = temp->next;		
		TNode* ret = temp->ptr2TNode;
		free(temp);
		return ret;
	}
	return NULL;
}

void add(Queue queue, TNode* Node) {
    /*元素在队尾入队*/
	QNode* temp = queue;
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->ptr2TNode = Node;
	newnode->next = NULL;
	while (temp->next != NULL) {
		temp = temp->next;
	}
	temp->next = newnode;
}
bool isEmpty(Queue queue) {
	/*判断队列是否为空*/
	return queue->next == NULL;
}
void levelOrder(SegmentTree T, Queue queue) {
    /*层序遍历线段树*/
	add(queue, T);
	while (!isEmpty(queue)) {
		TNode* node = delete(queue);
		visit(node);
		if (node->left != NULL) add(queue, node->left);
		if (node->right !=NULL) add(queue, node->right);
	}
}

标签:Queue,线段,Tree,TNode,queue,NULL,Segment,void
From: https://www.cnblogs.com/gjsun/p/17733444.html

相关文章

  • 【UVA 536】Tree Recovery 题解(根据遍历序列还原二叉树)
    小瓦伦丁非常喜欢玩二叉树。她最喜欢的游戏是随机构建查找节点中带有大写字母的二叉树。这是她创作的一个例子:为了给后代记录她的树,她为每棵树写下了两个字符串:预订单遍历(根、左子树、右子树)和有序遍历(左子树、根、右子树。对于上面绘制的树,预序遍历是DBACEGF,有序遍历是ABCDEFG......
  • Merkle Tree 简介
    Merkle树(MerkleTree)是一种树状数据结构,通常用于验证大规模数据集的完整性和一致性。它的名字来源于其发明者RalphMerkle。Merkle树在密码学、分布式系统和区块链等领域得到广泛应用,尤其在区块链中,它用于验证交易和区块的完整性,确保数据不被篡改。下面是Merkle树的介绍:1.......
  • 逻辑树(LogicTree)和可视化树(VisualTree)
    遍历逻辑树和可视化树FrameworkElementLevel.(FrameworkElementType).(FrameworkElementName)[DataContextType]publicstaticclassTreeHelper{publicstaticstringgetTree(FrameworkElementcontainer){StringBuildersb=newStringBuilder();......
  • 在线直播系统源码,取CTreeCtrl控件选中节点的文字
    在线直播系统源码,取CTreeCtrl控件选中节点的文字 voidCAboutDlg::OnSelchangedTree1(NMHDR*pNMHDR,LRESULT*pResult) {NM_TREEVIEW*pNMTreeView=(NM_TREEVIEW*)pNMHDR;//TODO:Addyourcontrolnotificationhandlercodehere    MessageBox(m_tree1.GetIte......
  • abc321E - Complete Binary Tree
    E-CompleteBinaryTree首先我们只考虑x子树中的答案,非常明显,一定是一个连续的区间,那么我们只需要找到两个端点即可,左端点一直往左走即可,但是右端点要注意,如果走不了,如果左端点存在,说明n就是我们的右端点。处理完子树之后往上跳即可,因为树高只有60#include<cstdio>#include<......
  • 线段树复习
    1.楼房重建经典题。先转化题意,将斜率转化为每个点的权值,发现答案是单调递增的。那么就是求单点修改的最长上升子序列。用线段树维护两个信息当前区间的最大值mx,当前区间最长上升子序列长度len。修改时单点修改即可,考虑如何合并两个区间的len。可以在线段树上二分。get(o,k)......
  • 使用Vue3+elementPlus的Tree组件实现一个拖拽文件夹管理
    目录1、前言2、分析3、实现4、踩坑4.1、拖拽辅助线的坑4.2、数据的坑4.3、限制拖拽4.4、样式调整1、前言最近在做一个文件夹管理的功能,要实现一个树状的文件夹面板。里面包含两种元素,文件夹以及文件。交互要求如下:创建、删除,重命名文件夹和文件可以拖拽,拖拽文件到文件夹中,或......
  • zTree使用记录
    <linkhref="zTree/zTreeStyle/zTreeStyle.css"rel="stylesheet"/><divid="treeDemo"class="ztree"></div><scriptsrc="zTree/jquery.ztree.all.js"type="text/javascript"><......
  • 内容搬迁至 SegmentFault #49a425
    https://www.cnblogs.com/zerofc/p/8710100.htmlhttps://www.cnblogs.com/zerofc/p/8710123.htmlhttps://www.cnblogs.com/zerofc/p/9038875.htmlhttps://www.cnblogs.com/zerofc/p/9940336.htmlhttps://www.cnblogs.com/zerofc/p/9974564.htmlhttps://www.cnblogs.com/z......
  • module开发过程tree_ shaking
    module开发过程tree_shakingmodule开发可以实现tree-shaking注意事项❓:什么情况下就会tree-shaking?......