数据结构之树的一些基本操作

是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。
头文件 tree.h

#ifndef __TREE_H__
#define __TREE_H__#include "error.h"struct _treeNode;                   // 结构体声明// 孩子结点链表的类型
typedef struct _childNode
{struct _treeNode * childNode;struct _childNode* next;        // 指向孩子结点链表下一个元素
}ChildNode;// 树节点类型
typedef char TreeData;
typedef struct _treeNode
{TreeData data;struct _treeNode * parent;      // 指向父节点的指针struct _treeNode * next;        // 指向链表的下一个结点struct _childNode* childList;   // 孩子链表的头节点int degree;                     // 结点的度
}TreeNode;typedef struct _tree
{struct _treeNode* head;         // 树链表的头节点int len;                        // 树结点个数
}Tree;// 定义一个函数指针类型
typedef void(*TreePrint)(TreeNode *node);Tree* Create_Tree();// pos 代表要插入结点父亲结点的位置
// 约定:
// 1 新插入的结点插入在当前父亲结点所有孩子的右边
// 2 根节点的位置是 0
int Insert_Tree (Tree* tree, TreeData data, int pos);// 打印树
void Display (Tree* tree, TreePrint pFunc);// 删除结点
int Delete (Tree* tree, int pos, TreeData *x);// 求指定位置树结点的值
int Tree_Get (Tree* tree, int pos, TreeData *x);// 清空树中所有的节点
int Tree_Clear (Tree* tree);// 树的销毁 
void Tree_Destroy   (Tree* tree);// 获取根节点的地址
TreeNode* Tree_Root (Tree* tree);// 求树的结点个数
int Tree_Count  (Tree* tree);// 求树的高度
int Tree_Height (Tree* tree);// 求树的度
int Tree_Degree (Tree* tree);// 打印
void printA (TreeNode* node);#endif  // __TREE_H__

源文件 tree.c

#include "tree.h"
#include <stdlib.h>Tree *Create_Tree()
{// 创建树节点Tree* tree = (Tree*) malloc(sizeof(Tree)/sizeof(char));if (NULL == tree){errno = MALLOC_ERROR;return NULL;}// 给树结点链表创建头节点tree->head = (TreeNode*) malloc(sizeof(TreeNode)/sizeof(char));if (NULL == tree->head){errno = MALLOC_ERROR;free (tree);return NULL;}tree->head->parent    = NULL;tree->head->childList = NULL;tree->head->next      = NULL;   // 代表树中没有结点// 空树结点为0tree->len = 0;return tree;
}int Insert_Tree (Tree* tree, TreeData data, int pos)
{if (NULL == tree || pos < 0 || pos > tree->len){errno = ERROR;return FALSE;}if (pos != 0 && tree->len == pos){errno = ERROR;return FALSE;}// 新建结点TreeNode* node = (TreeNode*) malloc(sizeof(TreeNode)/sizeof(char));if (NULL == node){   errno = MALLOC_ERROR;return FALSE;}node->data = data;node->next = NULL;// 创建该新节点的孩子结点链表的头节点node->childList = (ChildNode*) malloc(sizeof(ChildNode)/sizeof(char));if (NULL == node->childList){   errno = MALLOC_ERROR;free (node);return FALSE;}   node->childList->next      = NULL;node->childList->childNode = NULL;node->degree = 0;int i;// 找父节点TreeNode* parent = tree->head->next;     // 当前树节点的第一个结点for (i = 0; i < pos; i++){parent = parent->next;}node->parent = parent; // 在父亲结点的子结点链表中加入一个结点if (parent != NULL){// 创建一个孩子结点ChildNode* childnode = (ChildNode*) malloc(sizeof(ChildNode)/sizeof(char));if (NULL == childnode){errno = MALLOC_ERROR;free (node->childList);free (node);return FALSE;}childnode->childNode = node;childnode->next      = NULL;// 加入到父亲结点子结点链表当中ChildNode* tmp = parent->childList;   // 子结点链表的头节点while (tmp->next){   tmp = tmp->next;}tmp->next = childnode;parent->degree += 1;}TreeNode* tmp = tree->head;              // 树节点链表的头节点while (tmp->next){tmp = tmp->next;}tmp->next = node;tree->len += 1;return TRUE;
}// 递归打印结点
void r_display (TreeNode* node, int gap, TreePrint pFunc)
{if (NULL == node){return;}// 打印距离前一个结点的距离int i;for (i = 0; i < gap; i++){printf ("%c", '-');}// 打印结点自己// printf ("%c\n", node->data);pFunc (node);ChildNode* child = node->childList->next; // 该结点的第一个孩子// 打印该结点的孩子while (child){r_display (child->childNode, gap+4, pFunc);child = child->next;  // 下一个孩子}
}void Display (Tree *tree, TreePrint pFunc)
{if (NULL == tree){return;}r_display (tree->head->next, 0, pFunc);
}void r_delete (Tree *tree, TreeNode *node)
{if (NULL == tree || NULL == node)return;// 从树链表中移除这个结点,找node的前一个结点TreeNode* tmp = tree->head;  // 链表的头节点while (tmp->next){if (tmp->next == node){tmp->next = node->next;tree->len--;break;}tmp = tmp->next;}// 将父亲结点中子结点链表中指向node的结点删除TreeNode* parent = node->parent;if (NULL != parent){ChildNode* tmp = parent->childList;  // 子结点链表的头节点while (tmp->next){if (tmp->next->childNode == node){ChildNode* p = tmp->next;tmp->next    = p->next;free (p);parent->degree--;break;}tmp = tmp->next;}}// 将该结点的孩子结点删掉ChildNode* child = node->childList->next; // 子结点链表中的第一个结点while (child){ChildNode* pchild = child->next;r_delete (tree, child->childNode);child  = pchild;}free (node->childList);free (node);
}int Delete (Tree *tree, int pos, TreeData *x)
{if (NULL == tree || pos < 0 || pos > tree->len){errno = ERROR;return FALSE;}if (0 != pos && tree->len == pos){errno = ERROR;return FALSE;}int i;// 找结点TreeNode* current = tree->head->next;  for (i = 0; i < pos; i++){current = current->next;}*x = current->data;r_delete (tree, current);return TRUE;}int Tree_Get (Tree* tree, int pos, TreeData *x)
{if (NULL == tree || pos < 0 || pos > tree->len){errno = ERROR;return FALSE;}if (0 != pos && tree->len == pos){errno = ERROR;return FALSE;}int i;// 找结点TreeNode* current = tree->head->next;  for (i = 0; i < pos; i++){current = current->next;}*x = current->data;return TRUE;
}int Tree_Clear (Tree* tree)
{if (NULL == tree){errno = ERROR;return FALSE;}TreeData x;return Delete (tree, 0, &x);
}void Tree_Destroy (Tree* tree)
{if (NULL == tree){errno = ERROR;return;}Tree_Clear (tree);free (tree->head);free (tree);
}TreeNode* Tree_Root (Tree* tree)
{if (NULL == tree){errno = ERROR;return NULL;}return tree->head->next;
}int Tree_Count (Tree* tree)
{if (NULL == tree){errno = ERROR;return FALSE;}return tree->len;
}// 递归求高度
int r_height (TreeNode* node)
{if (NULL == node){return 0;}int subHeight = 0;int max       = 0;ChildNode* child = node->childList->next;while (child){subHeight = r_height (child->childNode);if (subHeight > max){max = subHeight;}child = child->next;}return max + 1;
}int Tree_Height (Tree* tree)
{if (NULL == tree){errno = ERROR;return FALSE;}int height = r_height (tree->head->next);return height;
}// 递归求度
int r_degree (TreeNode* node)
{if (NULL == node){return 0;}int max       = node->degree;int subDegree = 0;ChildNode* child = node->childList->next;while (child){subDegree = r_degree (child->childNode);if (subDegree > max){max = subDegree;}child = child->next;}return max;
}int Tree_Degree (Tree* tree)
{if (NULL == tree){errno = ERROR;return FALSE;}int degree = r_degree (tree->head->next);return degree;
}void printA (TreeNode* node)
{printf ("%c\n", node->data);
}

主函数 main.c

#include <stdio.h>
#include "tree.h"int main()
{Tree* tree = Create_Tree();if (NULL == tree){myError ("Create_Tree");return -1;}Insert_Tree (tree, 'A', 0);Insert_Tree (tree, 'B', 0);Insert_Tree (tree, 'C', 0);Insert_Tree (tree, 'D', 0);Insert_Tree (tree, 'E', 1);Insert_Tree (tree, 'F', 1);Insert_Tree (tree, 'H', 3);Insert_Tree (tree, 'I', 3);Insert_Tree (tree, 'J', 3);Insert_Tree (tree, 'X', 3);Insert_Tree (tree, 'Z', 8);Display (tree, printA);//printf ("删除B :\n");TreeData x;//Delete(tree, 1, &x);//Display(tree, printA);printf ("height = %d\n", Tree_Height(tree));printf ("degree = %d\n", Tree_Degree(tree));return 0;
}

error.h是我自己写的一个包含常见错误的头文件,这里我就不发了。

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

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

相关文章

利用FS寄存器获取KERNEL32.DLL基址算法的证明(ZZ)

转自&#xff1a;http://blog.csdn.net/int2e/archive/2008/01/09/2032732.aspxFS寄存器指向当前活动线程的TEB结构&#xff08;线程结构&#xff09; 偏移 说明 000 指向SEH链指针 004 线程堆栈顶部 008 线程堆栈底部 00C SubSystemTib 010 FiberData 014 ArbitraryUse…

很老很老的老偏方,小病一扫光

1、洋葱、生姜治头皮屑 ①将一个的洋葱头用纱布包好&#xff0c;用它揉擦头皮&#xff0c;24小时后用温水洗头&#xff0c;即可止头痒&#xff0c;除头皮屑。 ②先将生姜切片&#xff0c;放入锅里煮沸&#xff0c;待水温不烫的时候倒上适量醋&#xff0c;加水洗头。 2、小白果…

script 放置最佳位置以及 html 执行顺序

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 看到知乎上有很多讨论关于javascript位置的文章。所以特意留意了这方面的问题。 首先要了解到的是&#xff1a; html文件是自上而下的执…

677A

#include <stdio.h> int main() {int n, h;scanf("%d%d", &n, &h);int temp, width0;int i;for(i0; i<n; i){scanf("%d", &temp);if(temp<h)width;elsewidth2;}printf("%d\n", width);return 0; }转载于:https://www.cn…

数据结构之二叉树的一些基本操作

二叉树是树的特殊一种&#xff0c;具有如下特点&#xff1a;1、每个结点最多有两颗子树&#xff0c;结点的度最大为2。2、左子树和右子树是有顺序的&#xff0c;次序不能颠倒。3、即使某结点只有一个子树&#xff0c;也要区分左右子树。 头文件 BTree.h #ifndef __BTREE_H__ …

【Arduino】使用C#实现Arduino与电脑进行串行通讯

在给Arduino编程的时候&#xff0c;因为没有调试工具&#xff0c;经常要通过使用串口通讯的方式调用Serial.print和Serial.println输出Arduino运行过程中的相关信息&#xff0c;然后在电脑上用Arduino IDE的Serial Monitor来查看print出来的信息。Serial Monitor不仅可以接受Ar…

虚拟机NAT模式联网

阿里开源镜像软件&#xff1a;https://opsx.alibaba.com/mirror 如何使VMware ip与本机ip处于同一网段 https://blog.csdn.net/kakuma_chen/article/details/71425620 转载于:https://www.cnblogs.com/cdy0626/p/11131440.html

VS2008下最新X264(svn 2009.9)编译不过的解决办法

总有人说最新的版本 编译不过&#xff0c;搞的群、 论坛里到处都是这种求助贴。建议斑竹把这个解决办法放到醒目的位置&#xff0c;以减少噪音。科普开始1、编译问题由于MS的VS编译器对C99标准支持不好&#xff0c;不支持函数当中混合定义、声明变量。解决办法&#xff1a;在函…

node、npm、vue安装 -- VUE 项目 demo 实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 安装node&#xff1a; sudo yum install epel-release sudo yum install nodejs node --version // 安装好后查看版本2. 安装 npm …

用C语言实现简单的停车场管理

这个程序是利用栈和循环队列实现的&#xff0c;自己得先处理好逻辑关系就好了。由于题目没有要求&#xff0c;这个程序就没加重复判断&#xff0c;比如一辆车已经停在车位上或者便道上&#xff0c;再来一辆就判断不了了。关于栈&#xff0c;就是先进后出的思想&#xff0c;队列…

推荐一个配置linux服务的网站

该网站的各种linux服务的配置都是基于CentOS系统的 基本上各种linux服务都有了 http://www.server-world.info/en/转载于:https://www.cnblogs.com/Skyar/p/3582389.html

mariadb数据库增删改查

1.常用数据类型 1&#xff09;整数:int, bit 2&#xff09;小数:decimal    #decimal(5,2)表示共有五位数&#xff0c;保留两位小数 3&#xff09;字符串:varchar, char   4&#xff09;日期时间:date, time, datetime 5&#xff09;枚举类型(enu…

为什么你工作努力却没有起色?

成为职场达人&#xff0c;未必要经常挑灯夜战。相反&#xff0c;注意到下面几条&#xff0c;会让你少走弯路。 1&#xff09;成长的机会永远比眼前的待遇重要——做重要的事比多拿钱重要。 我知道在水木bbs上的worklife版本&#xff0c;每天都在上演的就是比较自己的第一个o…

《 Spring 实战 》(第4版) 读书笔记 (未完结,更新中...)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Pxx 表示在书的第 xx 页。 Spring 框架的核心是 Spring 容器。 1. (P7.) 构造器注入是依赖注入的方式之一。 紧耦合&#xff1a;在 …

数据结构排序法之希尔排序法(Shell Sort)

希尔排序&#xff0c;也叫递减增量排序&#xff0c;是插入排序的一种更高效的改进版本。希尔排序是不稳定的排序算法。 希尔排序是基于插入排序的以下两点性质而提出改进方法的&#xff1a; 1、插入排序在对几乎已经排好序的数据操作时&#xff0c;效率高&#xff0c;即可以达…

Windows To Ghost系统封装之必备软件集 - 好压

好压压缩软件&#xff08;HaoZip&#xff09;是强大的压缩文件管理器&#xff0c;是完全免费的新一代压缩软件&#xff0c;相比其它压缩软件系统资源占用更少&#xff0c;有更好的兼容性&#xff0c;压缩率比较高。 它提供了对ZIP、7Z和TAR文件的完整支持&#xff0c;能解压RAR…

js 弹窗并定时关闭

1. $(input).click(function() {prompt(点击成功, 2000) })function prompt(newName, time, fn) {var $div $(<div></div>);$div.css({position: fixed,top: 0,left: 0,width: 100%,height: 100%,z-index: 200,background-color: rgba(0,0,0,0.4),// background-c…

数据结构排序法之插入法

插入排序是一种简单直观的排序算法。它的工作原理非常类似于我们抓扑克牌。 对于未排序数据(右手抓到的牌)&#xff0c;在已排序序列(左手已经排好序的手牌)中从后向前扫描&#xff0c;找到相应位置并插入。 插入排序在实现上&#xff0c;通常采用in-place排序&#xff08;即…

XSLT学习笔记

1. 样式声明&#xff1a;<xsl:stylesheet>或<xsl:transform> 2. XSLT常用元素&#xff1a; 2.1 <xsl:template>&#xff1a;创建模板 Match属性的作用是使模板和XML元素相关联 e.g.:<xsl:template match"\">......</xsl:template&g…

职场:人生从没有最佳时机!一个离职客服人员的领悟

每个人都有感到失落迷惘的时候。 人生用专制又霸道的方式运行着&#xff0c;每当我们心想一切尘埃落定、生活稳固的时候&#xff0c;生活总爱给我们惊喜&#xff0c;粉碎我们短暂的安逸&#xff0c;让我们不得不重新思考。 「我走对路了吗?」 「我能够赚更多钱、爬到更高的地位…