【数据结构】二叉链表创建二叉树(C语言版)

一、思想(先序思想创建):

第一步先创建根节点,然后创建根节点左子树,开始递归创建左子树,直到递归创建到的节点下不继续创建左子树,也就是当下递归到的节点下的左子树指向NULL,结束本次左子树递归,返回这个节点的上一个节点,开始创建右子树,然后又开始以当下这个节点,继续递归创建左子树,左子树递归创建完,就递归创建右子树,直到递归结束返回到上一级指针节点(也就是根节点下),此时根节点左边子树创建完毕,开始创建右边子树,原理和根节点左边创建左右子树相同

二、创建二叉树

二叉树的操作通常使用递归方法,如果递归不太明白,建议去对此进行一下学习和练习。二叉树的操作可以分为两类,一类是需要改变二叉树的结构的,比如二叉树的创建、节点删除等等,这类操作,传入的二叉树的节点参数为二叉树指针的地址,这种参入传入,便于更改二叉树结构体的指针(即地址)。这里稍微有一点点绕,可能需要多思考一下

  • 如下是二叉数创建的函数,这里我规定,节点值为整数,如果输入的数为-1,则表示结束继续往下创建子节点的操作。然后我们使用递归的方法以此创建左子树和右子树

二叉树结构体初始化

为了更方便的使用二叉树结构体,可以使用 typedef 对结构体进行命名

typedef struct Tree{
 
 int data;					//	存放数据域
 struct Tree *lchild;			//	遍历左子树指针
 struct Tree *rchild;			//	遍历右子树指针
 
}Tree,*BitTree;

这里展示两种传参类型的创建方法,其中深意可多次参考理解,加深指针理解

(1)传一级参数方法

BitTree CreateLink()
{
	int data;
	int temp;
	BitTree T;
	
	scanf("%d",&data);		//	输入数据
	temp=getchar();			//	吸收空格
	
	if(data == -1){			//	输入-1 代表此节点下子树不存数据,也就是不继续递归创建
		
		return NULL;

	}else{
		T = (BitTree)malloc(sizeof(Tree));			//		分配内存空间
		T->data = data;								//		把当前输入的数据存入当前节点指针的数据域中
		
		printf("请输入%d的左子树: ",data);		
		T->lchild = CreateLink();					//		开始递归创建左子树
		printf("请输入%d的右子树: ",data);			
		T->rchild = CreateLink();					//		开始到上一级节点的右边递归创建左右子树
		return T;							//		返回根节点
	}	
	
}

(2)传二级参数方法

BitTree CreateLink(BitTree *T)		//	次数 T为指向根节点的指针的地址
{
	int data;	
	
	scanf("%d",&data);

	
	if(data == -1){
		
		*T=NULL;				//	结束递归时,让指针当前节点的指针地址的 指针 指向NULL

	}else{
		
		*T = (BitTree)malloc(sizeof(Tree));		//	对指向节点指针地址的指针 分配内存
	
		if(!(*T) ){			//	*T = NULL  表示分配内存失败,也就是结束递归创建了
			printf("内存分配失败\n");
			exit(-1);
		}
		
		
		(*T)->data = data;		//	给节点指针地址内的数据域,存入数据
		
		printf("请输入%d的左子树: ",data);
		CreateLink(&(*T)->lchild);		//	开始遍历左子树
		printf("请输入%d的右子树: ",data);
		CreateLink(&(*T)->rchild);		//	开始遍历右子树,遍历的思想文章开头处解释
			
	}
}

(1)一级参数完整例子:

#include<stdio.h>
#include<stdlib.h>

typedef struct Tree{
 
 int data;					//	存放数据域
 struct Tree *lchild;			//	遍历左子树指针
 struct Tree *rchild;			//	遍历右子树指针
 
}Tree,*BitTree;

BitTree CreateLink()
{
	int data;
	int temp;
	BitTree T;
	
	scanf("%d",&data);		//	输入数据
	temp=getchar();			//	吸收空格
	
	if(data == -1){			//	输入-1 代表此节点下子树不存数据,也就是不继续递归创建
		
		return NULL;

	}else{
		T = (BitTree)malloc(sizeof(Tree));			//		分配内存空间
		T->data = data;								//		把当前输入的数据存入当前节点指针的数据域中
		
		printf("请输入%d的左子树: ",data);		
		T->lchild = CreateLink();					//		开始递归创建左子树
		printf("请输入%d的右子树: ",data);			
		T->rchild = CreateLink();					//		开始到上一级节点的右边递归创建左右子树
		return T;							//		返回根节点
	}		
}

void ShowXianXu(BitTree T)			//		先序遍历二叉树
{
	if(T==NULL)
	{
		return;
	}
	printf("%d ",T->data);
	ShowXianXu(T->lchild);			//	递归遍历左子树
	ShowXianXu(T->rchild);			//	递归遍历右子树
}

int main()
{
	BitTree S;
	printf("请输入第一个节点的数据:\n");
	S = CreateLink();			//		接受创建二叉树完成的根节点
	ShowXianXu(S);				//		先序遍历二叉树
	
	return 0;	
} 

(2)二级参数完整例子

#include<stdio.h>
#include<stdlib.h>
typedef struct Tree{
	
	int data;
	struct Tree *lchild;
	struct Tree *rchild;
}Tree,*BitTree;

BitTree CreateLink(BitTree *T)		//	次数 T为指向根节点的指针的地址
{
	int data;	
	
	scanf("%d",&data);

	
	if(data == -1){
		
		*T=NULL;				//	结束递归时,让指针当前节点的指针地址的 指针 指向NULL

	}else{
		
		*T = (BitTree)malloc(sizeof(Tree));		//	对指向节点指针地址的指针 分配内存
	
		if(!(*T) ){			//	*T = NULL  表示分配内存失败,也就是结束递归创建了
			printf("内存分配失败\n");
			exit(-1);
		}
		
		
		(*T)->data = data;		//	给节点指针地址内的数据域,存入数据
		
		printf("请输入%d的左子树: ",data);
		CreateLink(&(*T)->lchild);		//	开始遍历左子树
		printf("请输入%d的右子树: ",data);
		CreateLink(&(*T)->rchild);		//	开始遍历右子树,遍历的思想文章开头处解释
			
	}	
	
}

void ShowXianXu(BitTree T)		//	先序遍历二叉树
{
	if(T==NULL)
	{
		return;
	}
	printf("%d ",T->data);
	ShowXianXu(T->lchild);		//	遍历左子树
	ShowXianXu(T->rchild);		//	遍历右子树
}

int main()
{
	BitTree *S;			//	创建指向这个结构体指针地址 的指针
	printf("请输入第一个节点的数据:\n");
	CreateLink(&S);		//	传二级指针地址
	ShowXianXu(S);		
	
	return 0;	
} 
首先,我们需要了解二叉树的顺序存储和二叉链表存储的概念。 1. 顺序存储:将二叉树按照层次遍历的顺序依次存储在一维数组中,若节点在数组中的下标为i,则其左子节点在数组中的下标为2i,右子节点在数组中的下标为2i+1。 2. 链式存储:将二叉树的每个节点定义为一个结构体,包含左右子节点以及节点的值。 以下是C语言代码实现通过二叉树的顺序存储输入,创建二叉链树: ```c #include <stdio.h> #include <stdlib.h> // 二叉树节点结构体 typedef struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; } TreeNode; // 创建二叉树(顺序存储) void createTree(int* arr, int len, TreeNode** root) { TreeNode** queue = (TreeNode**)calloc(len, sizeof(TreeNode*)); // 队列存储节点 TreeNode* node = NULL; for (int i = 0; i < len; i++) { if (arr[i] == -1) { // 空节点 node = NULL; } else { // 创建新节点 node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = arr[i]; node->left = NULL; node->right = NULL; } queue[i] = node; // 将节点存入队列 if (i > 0) { // 非根节点 int parent = (i - 1) / 2; // 计算父节点下标 if (queue[parent] != NULL) { // 父节点非空 if (i % 2 == 1) { // 左子节点 queue[parent]->left = node; } else { // 右子节点 queue[parent]->right = node; } } } } *root = queue[0]; // 返回根节点 free(queue); // 释放队列 } int main() { int arr[] = {1, 2, 3, 4, 5, -1, 6, -1, -1, 7}; // 示例输入 int len = sizeof(arr) / sizeof(int); TreeNode* root = NULL; createTree(arr, len, &root); return 0; } ``` 在示例中,我们定义了一个长度为10的顺序数组,其中-1表示空节点。通过createTree函数,将其转换为二叉链表存储的二叉树,并返回根节点。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咖喱年糕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值