C语言:利用排序二叉树进行排序

标签: C语言 二叉树 排序

by 小威威


1.引入

排序二叉树属于二叉树的一种,其主要特色在于构建二叉树与输出二叉树。二叉树的子树很有特点:左子树小于根结点,根结点小于右子树。通过排序二叉树,我们可以了解二叉树三种遍历的其中两种:即是中序遍历后序遍历。

中序遍历:中序遍历就是先读取左子树,再读取根结点,最后再读取右子树。
后序遍历:后序遍历就是先读取左子树,再读取右子树,最后再读取根结点。

补充:先序遍历就是先读取根结点,再读取左子树,最后再读取右子树。

2.代码

先上代码:
代码主要分为两部分:第一部分是main函数部分,第二部分是二叉树功能实现的部分。

/*main.h*/
#include<stdio.h>
#include<stdlib.h>
#include"tree.h"int main(void) {int node_num, i = 0, temp;Node *root = NULL;scanf("%d", &node_num);while (i < node_num) {scanf("%d", &temp);if (i == 0) root = init_root(temp);else insert_node(root, temp);i++;}traverse_tree_inorder(root);printf("\n");recycle_nodes(root);return 0;
}/*tree.h*/# include <stdlib.h>
# include <stdio.h>
typedef struct Node {struct Node *left;struct Node *right;int value;
} Node;
Node* init_root(int value) {Node *root;root = malloc(sizeof(Node));root->value = value;root->left = NULL;root->right = NULL;return root;
}
void insert_node(Node *p, int value) {Node *pArr;pArr = malloc(sizeof(Node));pArr->value = value;pArr->left = NULL;pArr->right = NULL;while (p->left != pArr && p->right != pArr) {while (value > p->value) {if (p->right == NULL) {p->right = pArr;return;} else {p = p->right;}}while (value < p->value) {if (p->left == NULL) {p->left = pArr;return;} else {p = p->left;}}}return;
}
void traverse_tree_inorder(Node *p) {if (p == NULL)return;traverse_tree_inorder(p->left);printf("%d ", p->value);traverse_tree_inorder(p->right);
}
void recycle_nodes(Node *p) {if (p == NULL)return;recycle_nodes(p->left);recycle_nodes(p->right);free(p);
}

本题的核心就是写tree.h的头文件。
该头文件需要实现以下函数:

/*中序遍历这个二叉树,按照升序输出,每个数之间有一个空格,最后一个数后也有一个空格。*/
void traverse_tree_inorder(Node *p)/*回收建立二叉树时开辟的内存空间,提示类似后序遍历。*/
void recycle_nodes(Node *p);/*将一个值为value的数插入到这个树中,但是要注意,需要插到那个地方,按照排序二叉树的要求来。*/
void insert_node(Node *p, int value);/*初始化根节点的值。*/
Node* init_root(int value);

首先是初始化根结点的值的函数:

Node* init_root(int value) {Node *root;root = malloc(sizeof(Node));root->value = value;root->left = NULL;root->right = NULL;return root;
}

这个函数很简单,只需给根结点开辟一个空间后初始化即可。注意,要把结点内的左右指针置为空。

其次是构建二叉树,这是本题的难点。

void insert_node(Node *p, int value) {Node *pArr;pArr = malloc(sizeof(Node));pArr->value = value;pArr->left = NULL;pArr->right = NULL;while (p->left != pArr && p->right != pArr) {while (value > p->value) {if (p->right == NULL) {p->right = pArr;return;} else {p = p->right;}}while (value < p->value) {if (p->left == NULL) {p->left = pArr;return;} else {p = p->left;}}}return;
}

这种构建二叉树的方法我称它为插入构造法。即将元素插入正确的位置。这种插入使得中序遍历输出一串有顺序的数字。那么,怎么插?

举个例子:
输入这些数据:23, 3, 53, 333, 2
输出: 2, 3, 23, 53, 333

第一个数字一定是给根结点赋值,所以不用判断。但接下来的数字都要进行判断,进而插入合适的位置。第二个数字3,将3与23比较,发现3小于23,所以将3成为23的左儿子。第三个数字53,将53与23比较,发现53大于23,因此53作为23的右儿子。第四个数字333,将333与23比较,发现333大于23,然而23的右儿子已经存在了,因此将333与23的右儿子53进行比较,发现333大于23,因此将333作为53的右儿子。第五个数字2,将其与23比较,发现2小于23,然而23的左儿子已经存在,因此将2与23的左儿子3比较,发现2小于3,因此将2作为3的左儿子。如此,排序二叉树就这样建立起来了。
你们可以通过这个例子了解插入的原理,然后自己用代码实现出来。

然后我要讲第三个函数中序遍历输出二叉树:

void traverse_tree_inorder(Node *p) {if (p == NULL)return;traverse_tree_inorder(p->left);printf("%d ", p->value);traverse_tree_inorder(p->right);
}

对于二叉树的遍历,我们一般通过递归实现,左子树一个递归,右子树一个递归,还有一个额外的操作。中序遍历就是先左子树的递归,再额外的操作,最后再右子树的递归。后序遍历也是这样,先左子树的递归,后右子树的递归,最后再额外的操作。前序遍历以此类推。此处的额外操作就是输出操作。

最后我要讲的是第四个函数:释放二叉树

void recycle_nodes(Node *p) {if (p == NULL)return;recycle_nodes(p->left);recycle_nodes(p->right);free(p);
}

因为二叉树的各个结点都是通过动态分配内存得来的,因此在程序终止前要将这些结点所分配的内存全部释放。不难发现其实释放的原理便是后序遍历。这里额外的操作就是释放内存,即free()。

3.总结

其实二叉树很好玩,只要你搞懂原理哈哈~

先序遍历:对一棵二叉树的前序遍历,先访问根结点,再访问左子树,然后访问右子树。

void preorder(Treenode *p) {if (p!=NULL){visit(p);preorder(p->left);preorder(p->right);}}

中序遍历:对一棵二叉树的中序遍历,先访问左子树,再访问根结点,然后访问右子树。

void inorder(Treenode *p) {if (p!=NULL){inorder(p->left);visit(p);inorder(p->right);}}

后序遍历:对一棵二叉树的后序遍历,先访问左子树,再访问右子树,然后访问根结点。

void postorder(Treenode *p) {if (p!=NULL){postorder(p->left);postorder(p->right);visit(p);}}

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


C语言:利用排序二叉树进行排序相关推荐

  1. 排序二叉树 SortBinaryTree

    排序二叉树 SortBinaryTree 排序二叉树是比较基本但是重要的算法,它在许多实际编码中都不可缺少,还有不少算法和数据结构都基于此.比如,二叉查找树,平衡二叉树,红黑树等等. SortBina ...

  2. 排序二叉树,平衡二叉树和红黑树的概念以及相关的操作讲解

    1. 排序二叉树 排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索. 排序二叉树要么是一棵空二叉树,要么是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有节点的值均 ...

  3. C语言利用图的邻接矩阵的存储方式实现拓扑排序

    C语言利用图的邻接矩阵的存储方式实现拓扑排序 在拓扑排序中,我们的对象是有向无环图,这种图是描述工程进行过程的有效工具.比如"课程开课顺序,施工进程,软件开发进程",我们在使用有向 ...

  4. 数据结构_排序二叉树(C语言)

    数据结构总目录 排序二叉树 1. 结构解析 排序二叉树的结构规则很简单,只遵循一个基本规则: 那就是在二叉树中,选择任意根结点,其左子树都比根节点小,右子树都比根节点大. 排序二叉树结构图 观察如下二 ...

  5. C语言排序算法 选择排序 插入排序 快速排序 qsort实现快排 堆排序

    常见排序算法 选择排序 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素 ...

  6. C语言——十四种内部排序算法【直接插入排序-冒泡排序-选择排序-插入排序-希尔排序-归并排序-快速排序-堆排序-折半插入排序-二分查找-路插入排序-表插入排序-简单选择排序-直接选择排序-树形选择】

    目录: 一:插入排序 A:直接插入排序 1.定义: 2.算法演示 实例1: 3.基本思想 4.排序流程图 实例1: B:希尔排序 1.定义: 2.算法演示 实例2: C:其他插入排序 a:折半插入排序 ...

  7. 一步一图一代码之排序二叉树

    作者:禅楼望月(http://www.cnblogs.com/yaoyinglong/) 属性: ①若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值. ②若它的右子树不为空,则右子树上所 ...

  8. 数据结构源码笔记(C语言):直接选择排序

    //实现直接选择排序算法#include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; typ ...

  9. c 语言从大到小排序算法,10 大经典排序算法(动图演示+ C 语言代码)

    原标题:10 大经典排序算法(动图演示+ C 语言代码) 来源:C语言与CPP编程 以前也零零碎碎发过一些排序算法,但排版都不太好,又重新整理一次,排序算法是数据结构的重要部分,系统地学习很有必要. ...

最新文章

  1. python如何帮我在投资中获取更高收益
  2. 不仅要“打假”,Facebook 还要治理视频直播中的裸露、暴力内容
  3. cad字体安装_浩辰CAD与AutoCAD兼容性测评大起底!
  4. 最长回文子串 hihocode 1032 hdu 3068
  5. 【网络安全】文件上传绕过思路总结
  6. solr mysql增量导入_Solr全量与增量导入
  7. 说一下 JVM 的主要组成部分?及其作用?
  8. happens-before
  9. mysql批量写入100万数据_Mysql数据库实践操作之————批量插入数据(100万级别的数据)-阿里云开发者社区...
  10. scratch3.0入门
  11. 最新版esight安装(sql_server安装+esight超级详细)
  12. Latex 图像、表格标题(题注)加脚注
  13. php 集成 spss,spss怎么导入数据
  14. 推荐系统-推荐模型总结
  15. Kettle入门案例
  16. vsftp虚拟账户登录失败331 Please specify the password.
  17. Kaggle实战之 房价预测案例
  18. 常见的软件测试人员面试问题
  19. layui点击按钮弹出另一个界面(增加界面),layui弹出层
  20. [C语言] 发牌洗牌

热门文章

  1. 直播疑难杂症排查(8)— 播放杂音、噪音、回声问题
  2. FANUC仿真安装指导
  3. uni-app 104退出和解散群聊(二)
  4. C4D暑期实践打卡7.31
  5. react和vue原理与比较
  6. 兵装开关电源,替代明纬电源的最佳选择
  7. Shell编程之函数与数组
  8. linux 下Qt 如何修改系统时间
  9. 百度飞桨EasyDL助力汽车零部件企业快速解锁AI应用
  10. 使用 Ambire 参加 Arbitrum 奥德赛活动的指南