结构说明:
是树结构,不过逻辑比较野,没有考虑性能,只关注结构塑造。
并没有使用递归或栈来生成树,而是为树定义了一套索引规则。
树的形状由上至下,依次新增节点,每一层的节点数为上一层的2倍,按1,2,4,8...排列,打印结果如下图
索引的方式为标识节点所在树的高度和从左到右的次序(从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(" ");
}
}
}