二叉树学习之二叉查找树

写在前面的话

最近接到几个大学同学研究生毕业不是签华为就是签百度,本人取经得到:操作系统、数据结构与算法、网络编程与数据库是面试中利器。想想自己工作2.5年月薪还不到10K,过着苦逼的码农生活,而他们一出校门就是大放光芒(最起码进入的公司就让人觉得牛逼哄哄的).本人痛定思痛,决定下大功夫学习一下数据结构与算法,我想这应该是根本吧.
之前也看过数据结构,但是一看到那乱七八糟的关系,就觉得还是研究一下别的东西,结果就是好多东西都是浅尝辄止,知子皮毛.
本人只贴出学习过程中的代码,以及一些发杂算法函数的详细注释,还有就是学习过程中遇到过的好的讲解URL,以供自己理解和后续的复习巩固,有不对的地方还需指正.

学习二叉树之前总感觉很抽象,最近看到亚嵌一个关于红黑树讲解的视频用到一个命令,能够将二叉树转换成图形打印出来,感觉很神奇,这个工具在Linux C编程一站式学习 中有提到过,
http://www.essex.ac.uk/linguistics/external/clmt/latex4ling/trees/tree/
有关应用会在后面代码测试中有提到,我想这应该是学习二叉树的一大利器,在此提出来。

源码

binarytree.h
#ifndef BINARYTREE_H
#define BINARYTREE_Htypedef struct node *link;
/***节点中的数据类型重定义*/
typedef unsigned char TElemType;struct node { TElemType item; link lchild, rchild;
};link init(TElemType VLR[], TElemType LVR[], int n);void pre_order(link t, void (*visit)(link));
void in_order(link t, void (*visit)(link));
void post_order(link t, void (*visit)(link));
void pprint(link t);
int count(link t);
int depth(link t);
void destroy(link t);/**
*http://www.cnblogs.com/bizhu/archive/2012/08/19/2646328.html 算法图解
*
*二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树,
*它或者是一棵空树;或者是具有下列性质的二叉树:
*(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
*(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
*(3)左、右子树也分别为二叉排序树;
*(4)排序二叉树的中序遍历结果是从小到大排列的.
*
*二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,为O(log n)。
*二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。
*
*搜索,插入,删除的复杂度等于树高,期望O(log n),最坏O(n)(数列有序,树退化成线性表)
*改进版的二叉查找树可以使树高为O(logn),如SBT,AVL,红黑树等.
*
*程序来源于Linux C编程一站式学习
*/
link bstSearch(link t, TElemType key);
link bstInsert(link t, TElemType key);
link bstDelete(link t, TElemType key);/***http://baike.baidu.com/view/593144.htm?fr=aladdin*平衡二叉树*/#endif
binarytree.c
/* binarytree.c */
#include <stdio.h>
#include <stdlib.h>
#include "binarytree.h"/***生成节点*@param item is node value*@returns link point to new node*/
static link make_node(TElemType item)
{link p = malloc(sizeof *p);p->item = item;p->lchild = p->rchild = NULL;return p;
}/***释放节点*@param link to free*/
static void free_node(link p)
{free(p);
}/***根据前序与中序序列来初始化二叉树*@param VLR 前序序列*@param LVR 中序序列*@param n 序列中数值个数*@returns NULL when n <= 0*@returns link pointer to new binarytree*/
link init(TElemType VLR[], TElemType LVR[], int n)
{link t;int k;if (n <= 0)return NULL;for (k = 0; VLR[0] != LVR[k]; k++);t = make_node(VLR[0]);t->lchild = init(VLR+1, LVR, k);t->rchild = init(VLR+1+k, LVR+1+k, n-k-1);return t;
}#ifdef RECU
/***前序遍历(跟左右)*@param t to visit*@param visit point to a func*/
void pre_order(link t, void (*visit)(link))
{if (!t)return;visit(t);pre_order(t->lchild, visit);pre_order(t->rchild, visit);
}/***中序序遍历(左跟右)*@param t to visit*@param visit point to a func*/
void in_order(link t, void (*visit)(link))
{if (!t)return;in_order(t->lchild, visit);visit(t);in_order(t->rchild, visit);
}/***中序序遍历(左右跟)*@param t to visit*@param visit point to a func*/
void post_order(link t, void (*visit)(link))
{if (!t)return;post_order(t->lchild, visit);post_order(t->rchild, visit);visit(t);
}
#endif/***遍历二叉树,生成用于tree工具的字符串*@param root to visit*/
void pprint(link root)
{printf("(");if (root != NULL) {printf("%d", root->item);pprint(root->lchild);pprint(root->rchild);}printf(")");
}int count(link t)
{if (!t)return 0;return 1 + count(t->lchild) + count(t->rchild);
}int depth(link t)
{int dl, dr;if (!t)return 0;dl = depth(t->lchild);dr = depth(t->rchild);return 1 + (dl > dr ? dl : dr);
}void destroy(link t)
{post_order(t, free_node);
}/***在bst中查找值为key的节点**1、若b是空树,则搜索失败,否则;*2、若x等于b的根节点的数据域之值,则查找成功;否则;*3、若x小于b的根节点的数据域之值,则搜索左子树;否则;*4、查找右子树.**@param t to search*@param key the value of link to find*@returns the link of the key*/
link bstSearch(link t, TElemType key)
{if (t == NULL)return NULL;if (t->item > key) {return bstSearch(t->lchild, key);} else if (t->item < key){return bstSearch(t->rchild, key);} else {return t;}
}/***在bst中插入值为key的节点**1、若t是空树,则将key作为根节点的值插入,否则;*2、若t->item大于key,则把key插入到左子树中,否则;*3、把key插入到左子树中.**@param t 要插入的 bst*@param key 要插入的值*@returns 插入后的bst*/
link bstInsert(link t, TElemType key)
{if (t == NULL) {return make_node(key);}if (t->item > key) {t->lchild = bstInsert(t->lchild, key);} else {t->rchild = bstInsert(t->rchild, key);}return t;
}/***在bst中删除值为key的节点**1、若t为空树,则直接返回NULL,否则;*2、若t->item大于key,bst左子树为bst左子树删除key后的bst,否则;*3、若t->item小于key,bst右子树为bst右子树删除key后的bst,否则;*4、若t->item == key:*		1.若其左右子树为NULL,返回NULL,即对其父节点赋值为NULL*		2.若其左子树不为NULL,则在其左子树中找到最大节点p,将p->item赋值给当前节点,还需要在其左子树中删除p->item,3.若其右子树不为NULL,则在其左子树中找到最小节点p,将p->item赋值给当前节点,还需要在其右子树中删除p->item,**@param t 要插入的 bst*@param key 要插入的值*@returns 插入后的bst*/
link bstDelete(link t, TElemType key)
{if (t == NULL)return NULL;if (t->item > key) t->lchild = bstDelete(t->lchild, key);else if (t->item < key)t->rchild = bstDelete(t->rchild, key);else {link p;if (t->lchild == NULL && t->rchild == NULL) {free_node(t);t = NULL;} else if (t->lchild){for (p = t->lchild; p->rchild; p = p->rchild);t->item = p->item;t->lchild = bstDelete(t->lchild, t->item);} else {for (p = t->rchild; p->lchild; p = p->lchild);t->item = p->item;t->rchild = bstDelete(t->rchild, t->item);}}return t;
}
测试程序
/* main.c */
#include <stdio.h>
#include <time.h>
#include "binarytree.h"#define RANGE  	50
#define N 		15void print_item(link p)
{printf("%d\t", p->item);
}void testBst()
{int i;link root = NULL;srand(time(NULL));for (i=0; i<N; i++)root = bstInsert(root, rand()%RANGE);printf("\\tree");pprint(root);printf("\n");TElemType key = rand() % RANGE;if (bstSearch(root, key)) {bstDelete(root, key);printf("\n%d\n", key);printf("\\tree");pprint(root);printf("\n");}
}void testInitByList()
{TElemType pre_seq[] = { 4, 2, 1, 3, 6, 5, 7 };TElemType in_seq[] = { 1, 2, 3, 4, 5, 6, 7 };link root = init(pre_seq, in_seq, 7);printf("\\tree");pprint(root);printf("\n");pre_order(root, print_item);putchar('\n');in_order(root, print_item);putchar('\n');post_order(root, print_item);putchar('\n');printf("count=%d depth=%d\n", count(root), depth(root));destroy(root);printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
}int main()
{//testInitByList();testBst();return 0;
}

对应的Makefie

#if you want to use recursive func,please make recu=y
ifeq (y, $(recu))CFLAGS += -DRECU
endififeq (y, $(debug))CFLAGS += -g
endifall:gcc $(CFLAGS) main.c binarytree.c binarytree.h -o treeclean:$(RM) tree

编译测试

在这里遍历二叉树只写了递归函数
在编译的时候用一下命令
make recu=y debug=y
运行结构如下:
\tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23(22()())(29()())))())(41()())))22
\tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23()(29()())))())(41()())))
好了接下来就是用工具tree,把这些字符串图形化
echo "\tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23(22()())(29()())))())(41()())))" | tree -b2
怎么样这个效果。


把b2改成b6

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

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

相关文章

二叉树学习之非递归遍历

二叉树递归遍历可谓是学过数据结构的同仁都能想一下就能写出来,但在应聘过程我们常常遇到的是写出一个二叉树非递归遍历函数,接着上篇文章写二叉树的非递归遍历,先难后易,一步一步的来. 先上代码: #include "binarytree.h" #include <stack> #include <queu…

二叉树学习之堆排序

认识堆是从堆排序开始的 二叉堆是完全二叉树或者是近似完全二叉树,堆存储在数组中: 根结点下标为0时,下标为n的元素的子结点下标分别为2*n1,2*n2,其父结点下标为(n-1)/2 二叉堆的特性: 1、父结点的键值总是>(<)任何一个子结点的键值 2、每个结点的左右子树都是二叉堆…

步入github世界

在源码的世界里&#xff0c;越来越多的优秀源码涌现&#xff0c;开源的世界不但代表他的优秀&#xff0c;也代表了他优秀的传播途径。 https://github.com/ github自从2008年现世&#xff0c;可谓是后来者居上。开源代码的公开库&#xff0c;优秀程序员的博客园&#xff0c;热心…

libevent学习__学习历程总结

The libevent API provides a mechanism to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached. Furthermore, libevent also support callbacks due to signals or regular timeouts.环境搭建 下载: http:…

redis☞ python客户端

安装 https://pypi.python.org/pypi/redis/ https://github.com/andymccurdy/redis-py 参照官网,安装命令 sudo pip install redis 或者 sudo easy_install redis 亦或 源码包执行sudo python setup.py install实例 >>> import redis >>> r redis.Redis(ho…

Catalan数应用

Catalan数应用 Catalan数应用原理卡特兰数经典应用括号化买票找零组合数与阶乘计算 卡特兰数又称卡塔兰数&#xff0c;是组合数学中一个常出现在各种计数问题中的数列。由以比利时的数学家欧仁查理卡塔兰 (1814–1894)命名。 其前几项为 : 1, 2, 5, 14, 42, 132, 429, 1430,…

统计整数n的二进制表示中1的个数

(1)逐位判断&#xff08;位运算&#xff09;int counter_ones(unsigned n){int counter 0;While (n) {counter n&1;n >>1;}return counter;}(2)一个整型不为0&#xff0c;那么二进制表示时&#xff0c;至少包含一位1。如果整数减去1&#xff0c;那么最右边的1变成0…

百度2015校园招聘软件开发笔试题及答案

简单题&#xff08;本题共30分&#xff09; 请简述Tcp-ip的3次握手以及4次挥手过程&#xff1f;并解释为何关闭连接需要4次挥手(10分) 详细答案参见TCP/IP协议三次握手与四次握手流程解析 TCP三次握手、四次挥手过程如下: 通常情况下&#xff0c;一个正常的TCP连接&#xf…

python常见数据结构

Python中常见的数据结构可以统称为容器&#xff08;container&#xff09;。序列&#xff08;如列表和元组&#xff09;、映射&#xff08;如字典&#xff09;以及集合&#xff08;set&#xff09;是三类主要的容器。 一、序列&#xff08;列表、元组和字符串&#xff09; 序列…

理解‘*‘,‘*args‘,‘**‘,‘**kwargs‘

原文Understanding ‘*’, ‘*args’,’**‘and’**kwargs’ 刚开始学习python的时候&#xff0c;对有关args,kwargs,*和**的使用感到很困惑。相信对此感到疑惑的人也有很多。我打算通过这个帖子来排解这个疑惑(希望能减少疑惑)。 让我们通过以下5步来理解&#xff1a; 通过…

MongoDb随笔,PyMongo简单使用

安装MongoDb 【更新2021-07-06】 https://www.mongodb.com/try/download/community 下载对应系统的软件版本&#xff08;CentOS7.9 mongod 4.4.6&#xff09;rpm -ivh mongodb-org-server-4.4.6-1.el7.x86_64.rpm安装服务systemctl start mongod启动服务rpm -ivh mongodb-org…

python中classmethod与staticmethod的差异及应用

类中三种函数的应用 #!/usr/bin/env python # -*- coding: utf-8 -*-class TClassStatic(object):def __init__(self, data):self.data datadef printself(*arg):# for item in arg:# print item.dataprint("printself: ", arg)staticmethoddef smethod(*arg):prin…

python3元类简介(metaclass)

在Python中可以用内置函数type查看对象的类型&#xff0c;isinstance查看某个对象是某个类实例&#xff0c;通过type可以实现动态类&#xff0c;以及通过metaclass实现动态类 type()与isinstance()判断对象类型 Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v…

linux ps 命令使用

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照&#xff0c;就是执行ps命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用top命令。 linux上进程有5种状态 ps命令使…

UML序列图总结

序列图主要用于展示对象之间交互的顺序。 序列图将交互关系表示为一个二维图。纵向是时间轴&#xff0c;时间沿竖线向下延伸。横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时&#xff0c;角色用一条虚线表示&#xff0c;当对象的过程处于激活…

UML用例图总结

用例图主要用来描述 用户、需求、系统功能单元 之间的关系。它展示了一个外部用户能够观察到的系统功能模型图。 【用途】&#xff1a;帮助开发团队以一种可视化的方式理解系统的功能需求。 用例图所包含的元素如下&#xff1a; 1. 参与者(Actor) 表示与您的应用程序或…

动态规划--换零钱

题目描述 想兑换100元钱&#xff0c;有1,2,5,10四种钱&#xff0c;问总共有多少兑换方法 递归解法 #include<iostream> using namespace std; const int N 100; int dimes[] {1, 2, 5, 10}; int arr[N1] {1}; int coinExchangeRecursion(int n, int m) //递归…

学生表 课程表 成绩表 教师表常用SQL语句

学生表 课程表 成绩表 教师表 50个常用sql语句 建表 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 ---- If database exists the same name datatable deletes it. IF EXISTS(SELECT TABLE_NAME FRO…

Linux网络编程常见面试题

概述 TCP和UDP是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议。 TCP&#xff1a;传输控制协议&#xff0c;一种面向连接的协议&#xff0c;给用户进程提供可靠的全双工的字节流&#xff0c;TCP套接口是字节流套接口(stream socket)的一种。UDP&#xff1a;用户…

sizeof与offsetof有关的结构体详解

sizeof与offsetof在程序中经常遇到&#xff0c;但在面试中其应用使得许多小伙伴吃闭门羹&#xff0c;被面试官问得哑口无言。接下来对两者的应用做详细介绍。 关于sizeof 定义 sizeof乃C/C中的一个操作符(operator), 简单的说其作用就是返回一个对象或者类型所占的内存字节数…