C语言 (非标准)树

218 阅读3分钟

结构说明:

是树结构,不过逻辑比较野,没有考虑性能,只关注结构塑造。

并没有使用递归或栈来生成树,而是为树定义了一套索引规则。

树的形状由上至下,依次新增节点,每一层的节点数为上一层的2倍,按1,2,4,8...排列,打印结果如下图

image.png

索引的方式为标识节点所在树的高度和从左到右的次序(从0开始),记为[高度][次序]。例如上图中的[6]节点,其位于树高度的第三层和左数第三个,则其索引值为[2][3]。

有关树节点的增删改操作也多借助索引值概念,通过封装好的根据索引获取节点的函数,定位目标节点。

代码

树节点结构

typedef struct TreeNode {

int value;
int info;
struct TreeNode* parent;
struct TreeNode* left;
struct TreeNode* right;

}TreeNode;

全局变量

  • int gl_treeSize;//树高度,正整数,如为0,则代表树为空,只有一个根节点的树高度为1
  • TreeNode* gl_rootNode;//树的根节点指针

初始化树函数

void initTree() {

//初始化树
int err = 0;
int maxLen = 0;
TreeNode* tmp = NULL;
if (gl_rootNode != NULL) {//从下到上,从左到右,依次删除节点
	tmp = gl_rootNode;
	for (int i = gl_treeSize-1;; i--) {
		maxLen = myPow(2, i);
		for (int j = 0; j < maxLen;j++) {
			tmp = tGetNodeByIndex(i, j);
			if (tmp != NULL) {
				tDelNode(tmp);
			}
		}
		gl_treeSize--;
		if (gl_treeSize == 0)
			break;
	}
}
gl_rootNode = NULL;
gl_treeSize = 0;

}

根据索引获取目标节点指针

TreeNode* tGetNodeByIndex(unsigned int y, unsigned int x) {

    /*
* 根据索引获取目标节点指针
* y:第几层,类似二维坐标系纵坐标(正整数)
* x:第几个,类似二维坐标系横坐标(整数)
* 索引顺序如下:
* 0
* 0 1
* 0 1 2
* 0 1 2 3
*/
unsigned int tmpX = x;
TreeNode* returnNode = gl_rootNode;
int maxLen = 0;

if (gl_treeSize == 0)
	return NULL;
if (y == 0 && x != 0) {
	printf("findByIndex:\ny == 0 && x != 0\n");
	return NULL;
}
if (x < 0 || x > myPow(2, y) - 1) {
	printf("findByIndex:\nx == 0 || x<-myPow(2, y - 1) || x > myPow(2, y - 1)\n");
	return NULL;
}
if (y > gl_treeSize + 1) {
	printf("findByIndex:\ny > gl_treeSize\n");
	return NULL;
}
if (y == 0)
	return gl_rootNode;

returnNode = gl_rootNode;
tmpX = x;
for (int i = 0;i < y;i++) {
	if (y-i == 1) {
		if (tmpX == 0) {
			return returnNode->left;
		}
		else {
			return returnNode->right;
		}
	}
	maxLen = myPow(2, y - i);
	//判断该层目标节点位于左叶下还是右叶下
	if (tmpX >= maxLen /2) {//右叶
		returnNode = returnNode->right;
		tmpX -= maxLen /2;
	}
	else{//左叶
		returnNode = returnNode->left;
	}
}

}

根据value值查找目标节点指针,可返回对应节点的索引

TreeNode* tFindNodeByValue(int destValue, int* destY, int* destX) {

//根据value值查找目标节点指针,可返回对应节点的索引
int maxLen = 0;
TreeNode* tmp = NULL;
for (int i = 0;i<gl_treeSize;i++) {
	maxLen = myPow(2, i);
	for (int j = 0; j < maxLen; j++) {
		tmp = tGetNodeByIndex(i,j);
		if (tmp == NULL)
			continue;
		if (tmp->value == destValue) {
			if (destY != NULL && destX != NULL) {
				*destY = i;
				*destX = j;
			}
			return tmp;
		}
	}
}
return NULL;

}

添加新节点

void tCreateNode(int value) {

//添加新节点
int i = 0, j = 0;
int maxLen = 0;
TreeNode* tmp = gl_rootNode;
if (gl_treeSize == 0) {
	gl_rootNode = (TreeNode*)malloc(sizeof(TreeNode));
	if (gl_rootNode == NULL)
		return;
	gl_rootNode->value = value;
	gl_rootNode->info = 0;
	gl_rootNode->parent = NULL;
	gl_rootNode->left = NULL;
	gl_rootNode->right = NULL;
	gl_treeSize++;
	return;
}

for (i = 0;i < gl_treeSize; i++) {
	maxLen = myPow(2, i);
	for (j = 0;j < maxLen; j++) {
		tmp = tGetNodeByIndex(i,j);
		if (tmp->left == NULL) {
			tmp->left = (TreeNode*)malloc(sizeof(TreeNode));
			if (tmp->left == NULL)
				return;
			tmp->left->value = value;
			tmp->left->parent = tmp;
			tmp->left->left = NULL;
			tmp->left->right = NULL;
			if(j == 0)
				gl_treeSize++;
			return;
		}
		else if (tmp->right == NULL) {
			tmp->right = (TreeNode*)malloc(sizeof(TreeNode));
			if (tmp->right == NULL)
				return;
			tmp->right->value = value;
			tmp->right->parent = tmp;
			tmp->right->left = NULL;
			tmp->right->right = NULL;
			return;
		}
	}
}

}

根据索引删除目标树节点

int tDelNodeByIndex(unsigned int y, unsigned int x) {

/*
*根据索引删除目标树节点
*返回值:
*-1:目标节点存在子节点
*-2:目标节点找不到
*0:成功删除节点
*/

TreeNode* tmp = tGetNodeByIndex(y, x);
if (tmp == NULL)//目标节点找不到
	return -2;
if (tmp->left != NULL || tmp->right != NULL)//目标节点存在子节点
	return -1;
else {
	tmp->parent->left = NULL;
	tmp->parent->right = NULL;
	tmp->value = 0;
	tmp->info = 0;
	free(tmp);
}
return 0;

}

通过节点指针删除目标树节点

int tDelNode(TreeNode* tNode) {

/*
通过节点指针删除目标树节点
返回值:
-1:目标节点存在子节点
-2:目标节点为空
0:成功删除节点
*/
if (tNode == NULL) {//目标节点为空
	return -2;
}
if (tNode->left != NULL || tNode->right != NULL)//目标节点存在子节点
	return -1;
else {
	if (tNode->parent == NULL) {
		tNode->value = 0;
		tNode->info = 0;
		free(tNode);
		return 0;
	}
	if (tNode->parent->left == tNode) {
		tNode->parent->left = NULL;
	}
	else if (tNode->parent->right == tNode) {
		tNode->parent->right = NULL;
	}
	tNode->value = 0;
	tNode->info = 0;
	free(tNode);
}
	
return 0;

}

打印整个树

void tPrintTree() {

//打印整个树
int maxLen = 0;
TreeNode* tmp = gl_rootNode;
for (int i = 0;i<gl_treeSize;i++) {
	maxLen = myPow(2, i);
	for (int j = 0; j < maxLen; j++) {
		tmp = tGetNodeByIndex(i, j);
		if (tmp == NULL) {
			printf("[null]");
		}
		else{
			printf("[%d]",tmp->value);
		}
		if (j == maxLen - 1)
			printf("\n");
		else
			printf(" ");
	}
}

}