二叉链表-创建、遍历(前序、中序、后序、非递归、层次)、复制、计算深度、结点数、销毁(C语言)

二叉树的定义

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 [1] 。
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点 [1]

来自百度百科。由“科普中国”科学百科词条编写与应用工作项目 审核 。

二叉树的性质

  1. 在二叉树的第 i 层最多有2i-1个结点(i>=1).
  2. 深度为 k 的二叉树最多有 2k - 1 个结点(k>=1) .
  3. 如果二叉树的终端结点数为 n0 ,度为 2 的结点数为 n2 ,
    则 n0 = n2 + 1 .
  4. 具有 n 个结点的完全二叉树深度为 [ log2 n ] + 1 ( [x] 表示不大于x的最大整数) .
  5. 对一个有 n 个结点的完全二叉树按层序编号,
    对任一结点 i 有:
    (1) i = 1 ,则结点 i 是二叉树的根,无双亲; i > 1,其双亲是结点[i/2]
    (2) 2 * i > n,则结点 i 无左孩子(结点 i 为叶子结点);否则左孩子是结点 2 * i .
    (3) 2 * i + 1 > n, 则结点 i 无右孩子,否则其右孩子是结点 2 * i + 1 .

二叉链表的基本操作

二叉树每个结点最多有两个孩子,为它设计一个数据域和两个指针域,即叫做二叉链表

二叉链表的结构定义

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0

typedef char BitreeElemType;
typedef struct BiNode {
	BitreeElemType data;
	struct BiNode* lchild, * rchild;
}BiNode;
typedef struct BiNode* BiTree;

前序遍历创建


/* 前序遍历创建 */
void CreateBiTree(BiTree* T)
{
	BitreeElemType ch;
	scanf(" %c", &ch);
	if (ch == '#') //我们用'#'表示空树
		*T = NULL;
	else 
	{
		*T = (BiTree)malloc(sizeof(BiNode));
		(*T)->data = ch;       //生成根结点
		CreateBiTree(&(*T)->lchild); //构造左子树
		CreateBiTree(&(*T)->rchild); //构造右子树
	}
}

前序、中序、后序遍历

/* 前序遍历 */
void PreOrderTraverse(BiTree T)
{
	if (!T) return;
	printf("%c\n", T->data);
	PreOrderTraverse(T->lchild); //先序遍历左子树
	PreOrderTraverse(T->rchild); //先序遍历右子树
}

/* 中序遍历 */
void InOrderTraverse(BiTree T)
{
	if (!T) return;
	InOrderTraverse(T->lchild); //先序遍历左子树
	printf("%c\n", T->data);
	InOrderTraverse(T->rchild); //先序遍历右子树
}

/* 后序遍历 */
void PostOrderTraverse(BiTree T)
{
	if (!T) return;
	PostOrderTraverse(T->lchild); //先序遍历左子树
	PostOrderTraverse(T->rchild); //先序遍历右子树
	printf("%c\n", T->data);

}

中序遍历的非递归算法(栈)

基本思路:
1.建立栈
2.根结点入栈 ,遍历左左子树
3.根结点出栈,输出根结点,遍历右子树

/* 中序遍历的非递归算法 */

void InOrderTraverse_Stack(BiTree T)
{
	SqStack S;
	InitStack(&S);
	BiTree p = T;
	while (p || !IsEmpty(S))
	{
		if (p)
		{
			Push(&S, p);//根结点入栈(顺序入栈一定要同类型呀,注意SElemType为Bitree)
			p = p->lchild;
		}
		else
		{
			Pop(&S,&p);//原栈顶元素给p(顺序处栈也要同类型,注意SElemType为Bitree)

			//输出根结点,遍历右子树
			printf("%c\n", p->data);
			p = p->rchild;
		}
	}
}
/*-------------------- ↓所需其它操作↓------------------------ */
//栈结构
#define MAXSIZE 100
typedef BiTree SElemType;
typedef struct {
	SElemType* top;  //顺序栈顶指针
	SElemType* base; //顺序栈底指针
	int stacksize;   //顺序栈最大容量
}SqStack;

/* 初始化顺序栈 */
int InitStack(SqStack* S)
{
	S->base = (SElemType*)malloc(MAXSIZE * sizeof(SElemType));
	if (!S->base) exit(-1);  //失败

	S->top = S->base;  //栈顶指针 = 栈底指针
	S->stacksize = MAXSIZE;

	return OK;
}
/* 判断空栈*/
int IsEmpty(SqStack S)
{
	if (S.base == S.top)
		return OK;
	else
		return ERROR;
}
/* 顺序栈的入栈 */
int Push(SqStack* S, BiTree Tree)
{
	if (S->top - S->base == S->stacksize)  //栈满了
		return ERROR;
	*++S->top = Tree;  // S->top++; *S->top = Tree;
	return OK;
}
/* 顺序栈的出栈 */
int Pop(SqStack* S,BiTree *Tree)
{
	if (S->top == S->base)   //空栈
		return ERROR;

	*Tree = *S->top--;  // *Tree = *S->top; S->top--; 
	return OK;
}

层次遍历(队列)

/* 层次遍历 */
void LevelOder(BiTree T)
{
	BiTree p = NULL;
	SqQueue Q;
	InitQueue(&Q);
	EnQueue(&Q, T);   //根结点入队
	while (Q.front != Q.rear)  //队不为空,循环
	{
		DeQueue(&Q, &p);   //出队结点p
		printf("%c\n", p->data);
		if (p->lchild)    //有左孩子,入队
			EnQueue(&Q, p->lchild);
		if (p->rchild)    //有右孩子,入队
			EnQueue(&Q, p->rchild);
	}
}
/*-------------------- ↓所需其它操作↓------------------------ */
//队列结构
typedef BiTree QElemType;
typedef struct {
	QElemType* base;  //动态分配存储空间
	int front;     //头指针
	int rear;      //尾指针
}SqQueue;

/* 初始化循环队列 */
int InitQueue(SqQueue* Q)
{
	Q->base = (QElemType*)malloc(MAXSIZE * sizeof(QElemType));
	if (!Q->base) exit(-1);
	Q->front = Q->rear = 0; //头指针与尾指针都为0
		return OK;
}
/* 循环队列入队 */
int EnQueue(SqQueue* Q, QElemType Tree)
{
	if ((Q->rear + 1) % MAXSIZE == Q->front)  //队满
		return ERROR;
	Q->base[Q->rear] = Tree;
	Q->rear = (Q->rear + 1) % MAXSIZE;  //队尾指针 + 1
	return OK;
}
/* 循环队列出队 */
int DeQueue(SqQueue* Q, QElemType* Tree)
{
	if (Q->front == Q->rear) return ERROR;
	*Tree = Q->base[Q->front];
	Q->front = (Q->front + 1) % MAXSIZE;  //队头指针 + 1
	return OK;
}

复制二叉树

/* 复制二叉树 */
void Copy(BiTree T, BiTree* NewT)
{
	if (!T)
	{
		*NewT = NULL;
		return;
	}
	else
	{
		*NewT = (BiTree)malloc(sizeof(BiTree));
		(*NewT)->data = T->data;
		Copy(T->lchild, &(*NewT)->lchild);
		Copy(T->rchild, &(*NewT)->rchild);
	}
}

计算深度

递归计算左右子树的深度,二叉树的深度为二者的较大值加 1 .

/* 计算深度 */
int Depth(BiTree T)
{
	if (!T) return 0;

	return Depth(T->lchild) > Depth(T->rchild) ? Depth(T->lchild) + 1 : Depth(T->rchild) + 1;

}

计算总结点数与叶子结点数

/* 计算总结点数 */
int Nodes(BiTree T)
{
	if (!T) return 0; //空树
	else
	return Nodes(T->lchild) + Nodes(T->rchild) + 1;
}

/* 计算叶子结点数 */
int LeafNodes(BiTree T)
{
	if (!T)    //空树
		return 0;
	if (!T->lchild && !T->rchild) //叶子结点
		return 1;
	else
		return LeafNodes(T->lchild) + LeafNodes(T->rchild);
}

后序销毁


/* 后序销毁二叉树 */
void Destroy(BiTree* T)
{
	if (!(*T)) return;
	else
	{
		Destroy(&(*T)->lchild);
		Destroy(&(*T)->rchild);
		free(*T);
		*T = NULL;
	}

}

  • 12
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个示例程序,用C语言实现了二叉树的建立、先序遍历中序遍历后序遍历层次遍历和统计树叶结点、层高等功能。 ```c #include <stdio.h> #include <stdlib.h> // 二叉结点结构体 typedef struct TreeNode { int data; // 结点据 struct TreeNode *left; // 左子树指针 struct TreeNode *right; // 右子树指针 } TreeNode; // 二叉树结构体 typedef struct BinaryTree { TreeNode *root; // 根结点指针 } BinaryTree; // 递归实现先序遍历 void preOrder(TreeNode *root) { if (root == NULL) { return; } printf("%d ", root->data); preOrder(root->left); preOrder(root->right); } // 递归实现中序遍历 void inOrder(TreeNode *root) { if (root == NULL) { return; } inOrder(root->left); printf("%d ", root->data); inOrder(root->right); } // 递归实现后序遍历 void postOrder(TreeNode *root) { if (root == NULL) { return; } postOrder(root->left); postOrder(root->right); printf("%d ", root->data); } // 利用队列实现层次遍历 void levelOrder(BinaryTree *tree) { if (tree == NULL || tree->root == NULL) { return; } Queue *queue = createQueue(); // 创建队列 enqueue(queue, tree->root); // 根结点入队 int level = 0; // 层号初始化为0 while (!isEmpty(queue)) { level++; // 进入下一层 printf("Level %d: ", level); // 输出层号 int levelSize = getSize(queue); // 当前层结点 for (int i = 0; i < levelSize; i++) { TreeNode *node = dequeue(queue); // 出队一个结点 printf("%d ", node->data); // 输出结点据 if (node->left != NULL) { enqueue(queue, node->left); // 左子树结点入队 } if (node->right != NULL) { enqueue(queue, node->right); // 右子树结点入队 } } printf("\n"); } destroyQueue(queue); // 销毁队列 } // 递归实现统计叶子结点 int countLeaves(TreeNode *root) { if (root == NULL) { return 0; } if (root->left == NULL && root->right == NULL) { // 叶子结点 return 1; } return countLeaves(root->left) + countLeaves(root->right); } // 递归实现统计结点 int countNodes(TreeNode *root) { if (root == NULL) { return 0; } return countNodes(root->left) + countNodes(root->right) + 1; } // 递归实现统计二叉树的层 int countLevels(TreeNode *root) { if (root == NULL) { return 0; } int leftLevels = countLevels(root->left); int rightLevels = countLevels(root->right); return (leftLevels > rightLevels ? leftLevels : rightLevels) + 1; } // 创建一个新的结点 TreeNode *createNode(int data) { TreeNode *node = (TreeNode *) malloc(sizeof(TreeNode)); node->data = data; node->left = NULL; node->right = NULL; return node; } // 递归实现向二叉树中插入新结点 void insertNode(TreeNode **root, int data) { if (*root == NULL) { *root = createNode(data); return; } if (data < (*root)->data) { insertNode(&((*root)->left), data); } else { insertNode(&((*root)->right), data); } } // 创建一个新的二叉树 BinaryTree *createTree() { BinaryTree *tree = (BinaryTree *) malloc(sizeof(BinaryTree)); tree->root = NULL; return tree; } // 递归实现销毁二叉树 void destroyTree(TreeNode *root) { if (root == NULL) { return; } destroyTree(root->left); destroyTree(root->right); free(root); } // 主函 int main() { BinaryTree *tree = createTree(); // 创建一个新的二叉树 insertNode(&(tree->root), 5); // 插入结点 insertNode(&(tree->root), 2); insertNode(&(tree->root), 8); insertNode(&(tree->root), 1); insertNode(&(tree->root), 3); insertNode(&(tree->root), 7); insertNode(&(tree->root), 9); printf("Preorder traversal: "); preOrder(tree->root); // 先序遍历 printf("\n"); printf("Inorder traversal: "); inOrder(tree->root); // 中序遍历 printf("\n"); printf("Postorder traversal: "); postOrder(tree->root); // 后序遍历 printf("\n"); printf("Level order traversal:\n"); levelOrder(tree); // 层次遍历 printf("Number of leaves: %d\n", countLeaves(tree->root)); // 统计叶子结点 printf("Number of nodes: %d\n", countNodes(tree->root)); // 统计结点 printf("Height of tree: %d\n", countLevels(tree->root)); // 统计层 destroyTree(tree->root); // 销毁二叉树 return 0; } ``` 以上代码演示了如何使用C语言二叉链表结构实现二叉树,并且递归实现了二叉树的先序遍历中序遍历后序遍历,利用队列实现了二叉树的层次遍历。同时还实现了统计树叶结点、层高等信息的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mirror_zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值