数据结构

数据结构

一、概念

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 。

二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点

二、完整代码

#include

#include

#include

/*声明结点*/

typedef struct Node {

int val;

struct Node* lchild, * rchild;

}Node;

/*声明树*/

typedef struct Tree {

int* root;

int n;

}Tree;

/*初始化新结点*/

Node* getNewNode(int val) {

Node* node = (Node*)malloc(sizeof(Node));

node->val = val;

node->lchild = node->rchild = NULL;

return node;

}

/*初始化新树*/

Tree *getNewTree() {

Tree* tree = (Tree*)malloc(sizeof(Tree));

tree->n = 0;

tree->root = NULL;

return tree;

}

/*二叉排序树 插值法 (插入成功:ret = 1,否则:ret=0) [递归] */

Node *insertNode(Node *root,int val,int *ret) {

if (root == NULL) {

*ret = 1;

/*初始化一个新结点,将结点插入树*/

return getNewNode(val);

}

/*如果值相等,返回原树*/

if (root->val == val)return root;

/*左小右大*/

if (root->val > val) {

root->lchild = insertNode(root->lchild, val,ret);

}

else {

root->rchild = insertNode(root->rchild, val,ret);

}

/*左小右大插完后,返回树结点(易遗漏)*/

return root;

}

void insert(Tree* tree,int val) {

if (tree == NULL)return;

/*flag判断是否插入成功(0:失败,1:成功)*/

int flag = 0;

/*注意:插入节点后接收返回的树节点*/

tree->root = insertNode(tree->root,val,&flag);//

/*节点数+1*/

tree->n += flag;

return;

}

/*递归输出结点值 【广义表输出】*/

void outputNode(Node *root) {

if (root == NULL)return;

/*先输出根节点的数值*/

printf("%d", root->val);

/*判断并递归到左右子树,输出值*/

if (root->lchild == NULL && root->rchild == NULL)return;

printf("(");

outputNode(root->lchild);

printf(",");

outputNode(root->rchild);

printf(")");

}

/*输出树(调用输出结点)*/

void outputTree(Tree *tree) {

if (tree == NULL)return;

printf("tree(%d):", tree->n);

outputNode(tree->root);

printf("\n");

}

/*清除树结点*/

void clearNode(Node* node) {

if (node == NULL)return;

free(node->lchild);

free(node->rchild);

free(node);

return;

}

/*清除树*/

void clearTree(Tree* tree) {

if (tree == NULL)return;

clearNode(tree->root);

free(tree);

return;

}

/// ////////////////////////////////前序遍历/////////////////////////

/*用了递归,并且要注意Node处判空操作*/

void preorderNode(Node* node) {

if (node == NULL) return;

printf("%d ", node->val);

preorderNode(node->lchild);

preorderNode(node->rchild);

return;

}

void preorder(Tree *tree) {

printf("pre order : ");

preorderNode(tree->root);

printf("\n");

return;

}

////////////////////////////////////中序遍历/////////////////////////

void inorderNode(Node* node) {

if (node == NULL) return;

inorderNode(node->lchild);

printf("%d ", node->val);

inorderNode(node->rchild);

return;

}

void inorder(Tree *tree) {

printf("in order : ");

inorderNode(tree->root);

printf("\n");

return;

}

/// ////////////////////////////////后序遍历/////////////////////////

void postorderNode(Node* node) {

if (node == NULL) return;

postorderNode(node->lchild);

postorderNode(node->rchild);

printf("%d ", node->val);

return;

}

void postorder(Tree *tree) {

printf("post order : ");

postorderNode(tree->root);

printf("\n");

return;

}

int main()

{

srand(time(0));

/*先声明一个树*/

Tree* tree = getNewTree();

for (int i = 0; i < 10; i++) {

int val = rand() % 100;

insert(tree,val);

/*每插入一个值,打印一次*/

outputTree(tree);

}

printf("\n");

preorder(tree);

inorder(tree);

postorder(tree);

clearTree(tree);

return 0;

}

三、分块理解

引入头文件,定义结点和数的数据类型

#include

#include

#include

/*声明结点*/

typedef struct Node {

int val;

struct Node* lchild, * rchild;

}Node;

/*声明树*/

typedef struct Tree {

int* root;

int n;

}Tree;

初始化新结点和树(结点包含 值 和 左右子树,数则存放 根节点 及 节点数量)

/*初始化新结点*/

Node* getNewNode(int val) {

Node* node = (Node*)malloc(sizeof(Node));

node->val = val;

node->lchild = node->rchild = NULL;

return node;

}

/*初始化新树*/

Tree *getNewTree() {

Tree* tree = (Tree*)malloc(sizeof(Tree));

tree->n = 0;

tree->root = NULL;

return tree;

}

定义插入二叉树的方法(向二叉树内插入数值,采用 左小右大 的 插入方法 [二叉搜索树])这里需要用到递归,务必认真

/*二叉排序树 插值法 (插入成功:ret = 1,否则:ret=0) [递归] */

Node *insertNode(Node *root,int val,int *ret) {

if (root == NULL) {

*ret = 1;

/*初始化一个新结点,将结点插入树*/

return getNewNode(val);

}

/*如果值相等,返回原树*/

if (root->val == val)return root;

/*左小右大*/

if (root->val > val) {

root->lchild = insertNode(root->lchild, val,ret);

}

else {

root->rchild = insertNode(root->rchild, val,ret);

}

/*左小右大插完后,返回树结点(易遗漏)*/

return root;

}

void insert(Tree* tree,int val) {

if (tree == NULL)return;

/*flag判断是否插入成功(0:失败,1:成功)*/

int flag = 0;

/*注意:插入节点后接收返回的树节点*/

tree->root = insertNode(tree->root,val,&flag);//

/*节点数+1*/

tree->n += flag;

return;

}

通过递归将树打印出,同样需要细心

/*递归输出结点值 【广义表输出】*/

void outputNode(Node *root) {

if (root == NULL)return;

/*先输出根节点的数值*/

printf("%d", root->val);

/*判断并递归到左右子树,输出值*/

if (root->lchild == NULL && root->rchild == NULL)return;

printf("(");

outputNode(root->lchild);

printf(",");

outputNode(root->rchild);

printf(")");

}

/*输出树(调用输出结点)*/

void outputTree(Tree *tree) {

if (tree == NULL)return;

printf("tree(%d):", tree->n);

outputNode(tree->root);

printf("\n");

}

定义清除树的方法

/*清除树结点*/

void clearNode(Node* node) {

if (node == NULL)return;

free(node->lchild);

free(node->rchild);

free(node);

return;

}

/*清除树*/

void clearTree(Tree* tree) {

if (tree == NULL)return;

clearNode(tree->root);

free(tree);

return;

}

前、中、后序遍历

/// ////////////////////////////////前序遍历/////////////////////////

/*用了递归,并且要注意Node处判空操作*/

void preorderNode(Node* node) {

if (node == NULL) return;

printf("%d ", node->val);

preorderNode(node->lchild);

preorderNode(node->rchild);

return;

}

void preorder(Tree *tree) {

printf("pre order : ");

preorderNode(tree->root);

printf("\n");

return;

}

////////////////////////////////////中序遍历/////////////////////////

void inorderNode(Node* node) {

if (node == NULL) return;

inorderNode(node->lchild);

printf("%d ", node->val);

inorderNode(node->rchild);

return;

}

void inorder(Tree *tree) {

printf("in order : ");

inorderNode(tree->root);

printf("\n");

return;

}

/// ////////////////////////////////后序遍历/////////////////////////

void postorderNode(Node* node) {

if (node == NULL) return;

postorderNode(node->lchild);

postorderNode(node->rchild);

printf("%d ", node->val);

return;

}

void postorder(Tree *tree) {

printf("post order : ");

postorderNode(tree->root);

printf("\n");

return;

}

主函数:随机对树进行10次插值操作,再调用前中后序遍历,清空二叉树

int main()

{

srand(time(0));

/*先声明一个树*/

Tree* tree = getNewTree();

for (int i = 0; i < 10; i++) {

int val = rand() % 100;

insert(tree,val);

/*每插入一个值,打印一次*/

outputTree(tree);

}

printf("\n");

preorder(tree);

inorder(tree);

postorder(tree);

clearTree(tree);

return 0;

}

相关推荐

樾字取名男孩名字大全
365提款会被冻结卡吗

樾字取名男孩名字大全

📅 08-13 👁️ 6305
中船重工28个研究所排名有哪些?一文看懂各所实力对比!
365bet亚洲版体育在线

中船重工28个研究所排名有哪些?一文看懂各所实力对比!

📅 08-23 👁️ 4946
常见的喹啉合成反应
365提款会被冻结卡吗

常见的喹啉合成反应

📅 08-06 👁️ 612