C Primer Plus--高级数据结构之二叉树
C Primer Plus--高级数据结构表示之二叉树
二叉搜索树 Binary Search Tree
二叉树是一种高级数据结构。树中的每个节点都包含一个项目和两个指向其他节点的指针。
每个节点都有两个子节点:左节点、右节点。在左节点中的项目是父节点中项目的前序向,而在右节点中的项目是父节点项目的后序向。
二叉树中每一个节点本身是其后代节点的根,此节点与其后代节点构成一个子树,子树有左右之分。
用C构建二叉树ADT
首先明确二叉树结构:
二叉树或者是一个空的节点集合(空树),或者是一个指定某个节点为根的节点集合。每个节点有两个作为其后代的树,称为左子树和右子树。
每个子树本身又是一个二叉树,也包含它是个空树的可能性。
二叉搜索树是有序的二叉树,它的每个节点包含一个项目,它的所有左子树的项目排在根项目的前面,而根项目排在所有右子树项目的前面。
而且二叉树的类型操作有:
- 树初始化为空树
- 查询树是否为空
- 查询树是否已满
- 查询树中项目个数
- 向树中添加项目
- 从树中删除项目
- 从树中搜索一个项目
- 遍历树中所有项目
- 清空树
树结构的定义
假设一个项目中包含一部电影的名字,上映年份,我们定义项目为Item:定义节点Node结构,包含一部电影,节点的左子节点,节点的右子节点指针;定义结构Tree包含根节点指针、树的项目个数。
#define TITLE_MAX_CHARS 40
typedef struct movie {
char title[TITLE_MAX_CHARS];
int year;
} Item;
typedef struct node {
Item movie;
struct movie * left;
struct movie * right;
} Node;
typedef struct tree {
Node * root;
int size;
} Tree;
定义好了数据结构,下面进行树操作的定义:
//初始化树
void InitializeTree(Tree * ptoTree);
//树是空的吗?
bool TreeIsEmpty(const Tree * ptoTree);
//树满了吗?假定我们队树的最大项目树有要求
bool TreeIsFull(const Tree * ptoTree);
//查询树的项目数
bool TreeSize(const Tree * ptoTree);
//向树添加项目
bool AddMovieToTree(const Item * ptoItem,Tree * ptoTree);
//从树删除项目
bool DleteMovieFromTree(const Item * ptoItem,Tree * ptoTree);
//项目是否重复?
bool IsInTree(const Item * ptoItem, Tree * ptoTree);
//遍历树的项目
void TraverseTree(const Tree * ptoTree,void (* ptoFunc) (Item item));
完整程序如下:
binarySearchTree.h:
//
// Created by bob on 2018/11/14.
//
#ifndef LEARNINGC_BINARYSEARCHTREE_H
#define LEARNINGC_BINARYSEARCHTREE_H
#include <stdbool.h>
#define MAX_ITEMS 40
#define TITLE_MAX_CHARS 40
typedef struct movie {
char title[TITLE_MAX_CHARS];
int year;
} Item;
typedef struct node {
Item movie;
struct node * left;
struct node * right;
} Node;
typedef struct tree {
Node * root;
int size;
} Tree;
typedef struct pair {
Node * parent;
Node * child;
} Pair;
void InitializeTree(Tree * ptoTree);
bool TreeIsEmpty(const Tree * ptoTree);
bool TreeIsFull(const Tree * ptoTree);
int TreeSize(const Tree * ptoTree);
bool AddMovieToTree(const Item * ptoItem,Tree * ptoTree);
bool DleteMovieFromTree(const Item * ptoItem,Tree * ptoTree);
bool IsInTree(const Item * ptoItem, Tree * ptoTree);
void TraverseTree(const Tree * ptoTree,void (* ptoFunc) (Item item));
void ClearTree(Tree * ptoTree);
#endif //LEARNINGC_BINARYSEARCHTREE_H
binarySearchTree.c:
//
// Created by bob on 2018/11/14.
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "binarySearchTree.h"
static Pair SeekItem(const Item *, const Tree *);
static bool ToLeft(const Item * p1, const Item * p2);
static bool ToRight(const Item * p1, const Item * p2);
static Node * MakeNode(const Item * ptoItem);
static bool AddNodeToTree(Node * new_node, Node * root);
static bool DeleteNode(Node ** p);
static void Traverse(const Tree * ptoTree,void (*pfunc) (Item movie));
static void InOrder(const Node * parent, void (*pfunc) (Item movie));
static void DeleteAllNodes(Node * parent);
Pair SeekItem(const Item * ptoItem, const Tree * ptoTree) {
Pair scan;
scan.parent = NULL;
scan.child = ptoTree->root;
if(scan.child == NULL)
return scan;
while (scan.child != NULL){
if(ToLeft(ptoItem,&(scan.child->movie))){
scan.parent = scan.child;
scan.child = scan.child->left;
} else if(ToRight(ptoItem,&(scan.child->movie))){
scan.parent = scan.child;
scan.child = scan.child->right;
} else{
break;
}
}
return scan;
}
bool ToLeft(const Item *p1, const Item *p2) {
int compl;
if((compl = strcmp(p1->title,p2->title)) < 0)
return true;
else if((compl = strcmp(p1->title,p2->title)) == 0 && p1->year < p2->year)
return true;
else
return false;
}
bool ToRight(const Item *p1, const Item *p2) {
int compl;
if((compl = strcmp(p1->title,p2->title)) > 0)
return true;
else if((compl = strcmp(p1->title,p2->title)) == 0 && p1->year > p2->year)
return true;
else
return false;
}
Node * MakeNode(const Item *ptoItem) {
Node * new_node;
new_node = (Node *) malloc(sizeof(Node));
if(new_node == NULL){
fprintf(stderr,"Can not allocate memory to create a node.\n");
return NULL;
}
if(ptoItem != NULL){
new_node->movie = * ptoItem;
new_node->left = NULL;
new_node->right = NULL;
}
return new_node;
}
bool AddNodeToTree(Node *new_node, Node * root) {
if(ToLeft(&new_node->movie,&root->movie)){
if(root->left == NULL)
root->left = new_node;
else
AddNodeToTree(new_node,root->left);
}else if(ToRight(&new_node->movie,&root->movie)){
if(root->right == NULL)
root->right = new_node;
else
AddNodeToTree(new_node,root->right);
}else{
fprintf(stderr,"Error in locating the inserting index of this node.\n");
exit(1);
}
return true;
}
bool DeleteNode(Node ** p) {
Node * p_temp;
puts("Deleting the movie:");
puts((*p)->movie.title);
if((*p)->left == NULL){
p_temp = *p;
*p = (*p)->right;
free(p_temp);
} else if((*p)->right == NULL){
p_temp = *p;
*p = (*p)->left;
free(p_temp);
}else{
for (p_temp = (*p)->left;p_temp->right != NULL;p_temp = p_temp->right)
continue;
p_temp->right = (*p)->right;
p_temp = *p;
*p = (*p)->left;
free(p_temp);
}
}
void Traverse(const Tree *ptoTree, void (*pfunc)(Item)) {
if(ptoTree != NULL)
InOrder(ptoTree->root,pfunc);
}
void InOrder(const Node *parent, void (*pfunc)(Item)) {
if(parent != NULL){
InOrder(parent->left,pfunc);
(*pfunc)(parent->movie);
InOrder(parent->right,pfunc);
}
}
void DeleteAllNodes(Node *parent) {
Node * ptoRight;
if(parent != NULL){
ptoRight = parent->right;
DeleteAllNodes(parent->left);
free(parent);
DeleteAllNodes(ptoRight);
}
}
void InitializeTree(Tree *ptoTree) {
ptoTree -> root = NULL;
ptoTree->size=0;
}
bool TreeIsEmpty(const Tree *ptoTree) {
if(ptoTree->root == NULL)
return 1;
else
return 0;
}
bool TreeIsFull(const Tree *ptoTree) {
if(ptoTree->size >= MAX_ITEMS)
return true;
else
return false;
}
int TreeSize(const Tree *ptoTree) {
return ptoTree->size;
}
bool AddMovieToTree(const Item * ptoItem, Tree * ptoTree) {
if(ptoItem == NULL | strlen(ptoItem->title) == 0 | ptoItem->year < 1800){
fprintf(stderr,"The movie you are adding has something wrong.");
return false;
}
if(TreeIsFull(ptoTree)){
fprintf(stderr,"The tree is full. You can not add a movie to a full tree");
return false;
}
if(SeekItem(ptoItem,ptoTree).child != NULL){
fprintf(stderr,"Trying to add duplicate movie.\n");
}
Node * new_node;
new_node = MakeNode(ptoItem);
// if(new_node == NULL){
//
// }//无需判断new_node是否为空指针,MakeNode函数里已经做过了
ptoTree->size++;
if(ptoTree->root == NULL)
ptoTree->root = new_node;
else
AddNodeToTree(new_node,ptoTree->root);
return true;
}
bool DleteMovieFromTree(const Item *ptoItem, Tree *ptoTree) {
Pair scan;
scan = SeekItem(ptoItem,ptoTree);
if(scan.child == NULL)
return false;
if(scan.parent == NULL)
DeleteNode(&ptoTree->root);
else if(scan.parent->left == scan.child)
//这里不能传scan.child,虽染这两个指向的是同一个node,但我们必须得传父节点持有的指针的指针
DeleteNode(&scan.parent->left);
else
DeleteNode(&scan.parent->right);
ptoTree->size--;
return true;
}
bool IsInTree(const Item *ptoItem, Tree *ptoTree) {
return SeekItem(ptoItem,ptoTree).child != NULL;
}
void TraverseTree(const Tree *ptoTree, void (*ptoFunc)(Item)) {
Traverse(ptoTree,ptoFunc);
}
void ClearTree(Tree *ptoTree) {
if(ptoTree == NULL)
return;
else
DeleteAllNodes(ptoTree->root);
ptoTree->root = NULL;
ptoTree->size = 0;
}
好乱,日后再改。
C Primer Plus--高级数据结构之二叉树的更多相关文章
- Python中的高级数据结构
数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionar ...
- Python中的高级数据结构详解
这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...
- Python中的高级数据结构(转)
add by zhj: Python中的高级数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数 ...
- 数据结构(5) 第五天 快速排序、归并排序、堆排序、高级数据结构介绍:平衡二叉树、红黑树、B/B+树
01 上次课程回顾 希尔排序 又叫减少增量排序 increasement = increasement / 3 + 1 02 快速排序思想 思想: 分治法 + 挖坑填数 分治法: 大问题分解成各个小问 ...
- GO语言的进阶之路-Golang高级数据结构定义
GO语言的进阶之路-Golang高级数据结构定义 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们之前学习过Golang的基本数据类型,字符串和byte,以及rune也有所了解, ...
- 20181022 考试记录&高级数据结构
题目 W神爷的题解 高级数据结构 T1: 其实是一道easy题,$O(n^3log n)$ 也是能卡过去的,本着要的70分的心态,最后尽然A了. 如果是正解则是$O(n^3)$,当确定你要选择的列时, ...
- python数据结构之二叉树的统计与转换实例
python数据结构之二叉树的统计与转换实例 这篇文章主要介绍了python数据结构之二叉树的统计与转换实例,例如统计二叉树的叶子.分支节点,以及二叉树的左右两树互换等,需要的朋友可以参考下 一.获取 ...
- 高级数据结构之 BloomFilter
高级数据结构之 BloomFilter 布隆过滤器 https://en.wikipedia.org/wiki/Bloom_filter A Bloom filter is a space-effic ...
- C++数据结构之二叉树
之前打算编算法类的程序,但是搞了几次英雄会后,觉得作为一个还在学习阶段的学生,实在是太浪费时间了,并不是没意义,而是我的基础还不牢固啊.所以转变了思路,这个学期打算分别用C++.Python.Java ...
随机推荐
- Resharper2019 1.2破解教程
下载安装 Resharper 去Resharper官网下载安装 Resharper官网地址 Resharper下载地址 破解 (破解dll百度网盘链接)[https://pan.baidu.com/s ...
- 两台Windows的 IIS 应用站点 基于NLB + ARR 实现双机热备和负载
IIS负载均衡中我们使用微软的ARR,但提到网站的高可用性,ARR只能做请求入口的消息分发服务,这样如果我们的消息分发服务器给down掉啦,那么做再多的应用服务集群也都枉然. 这里我们主要针对解决这一 ...
- C# 调用 C++ dll的两种方式
目录: 1.非托管方式 2.托管方式 3.介绍 extern "C" 4.介绍 DllImport 1.非托管方式 第一种,非托管方式:调用类和方法https://www.co ...
- Mycat使用--分库分表和读写分离
Mycat分库分表读写分离 1. 模拟多数据库节点 2. 配置文件 具体操作参看: https://blog.csdn.net/vbirdbest/article/details/83448757 写 ...
- Java调用Http/Https接口(2)--HttpURLConnection/HttpsURLConnection调用Http/Https接口
HttpURLConnection是JDK自身提供的网络类,不需要引入额外的jar包.文中所使用到的软件版本:Java 1.8.0_191. 1.服务端 参见Java调用Http接口(1)--编写服务 ...
- JQuery+Bootstrap 自定义全屏Loading插件
/** * 自定义Loading插件 * @param {Object} config * { * content[加载显示文本], * time[自动关闭等待时间(ms)] * } * @param ...
- C#-将照片存入到SQL SERVER
将存照片的字段设为image类型. using System; using System.Collections.Generic; using System.ComponentModel; using ...
- linux服务器管理常用命令
1.ps命令 (Processes Status) ps这个命令是查看系统进程,ps 是显示瞬间行程的状态,并不动态连续. ==============ps 的参数说明================ ...
- Docker基础用法篇
Docker基础用法篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装docker 1>.依赖的基础环境 64 bits CPU Linux Kerner 3.10+ ...
- Tarjan算法分解强连通分量(附详细参考文章)
Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...