Computer experiment of data structure (Chapter 6) - tree and binary tree III

Posted by texmansru47 on Sat, 18 Dec 2021 21:31:39 +0100

1. The weighted path length (WPL) of a binary tree is the sum of the weighted path lengths of all leaf nodes in the binary tree. Given a binary tree T, it is stored in a binary linked list, and the node structure is


The weight field of the leaf node stores the non negative weight of the node. Set root as the pointer to the root node of T.

typedef struct BiTNode
{
	int weight;
	struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;

int wpl = 0; //Define a global variable to store wpl
int wpl_PreOrder(BiTNode* root, int deep)
{
	if (root != NULL)
	{
		if (root->lchild == NULL && root->rchild == NULL) wpl += deep * root->weight; //If it is a leaf node, wpl is accumulated
		wpl_PreOrder(root->lchild, deep + 1); //Left subtree recursive traversal
		wpl_PreOrder(root->rchild, deep + 1); //Recursive traversal of right subtree
		return wpl;
	}
}

wpl_PreOrder(root, 0);

2. Convert the given expression tree (binary tree) into an equivalent infix expression (reflecting the calculation order of operators through parentheses) and output it.

  • Algorithm idea: the outermost layer of the expression (corresponding to the root node) and the operand (corresponding to the leaf node) do not need to add parentheses.
void InBtreeToExp(BiTNode* root, int deep)
{
	if (root == NULL) return; //Null node return
	else if (root->lchild == NULL && root->rchild == NULL) //If leaf node
		printf("%c", root->data); //Output operand without parentheses
	else
	{
		if (deep > 1) printf("("); //If there is a subexpression, add a layer of parentheses
		InBtreeToExp(root->lchild, deep + 1);
		printf("%c", root->data); //Output operator
		InBtreeToExp(root->rchild, deep + 1); 
		if (deep > 1) printf(")"); //If there is a subexpression, add a layer of parentheses
	}
}
InBtreeToExp(T1, 1);

Operation results

3. Judge whether the node with the value of x and the node with the value of y are brothers to each other, assuming that such node value is unique.

bool Brother(BiTNode* b, ElemType x, ElemType y)
{
	bool flag;
	if (b == NULL) return false;
	else
	{
		if (b->lchild != NULL && b->rchild != NULL)
		{
			if ((b->lchild->data == x && b->rchild->data == y) || (b->lchild->data == y && b->rchild->data == x))
			return true;
		}
			flag = Brother(b->lchild, x, y);
			if (flag == true) return true;
			else Brother(b->rchild, x, y);
	}
}

Operation results

4. Using the preorder traversal method to find the descendant nodes of the node with the value of x in binary tree b, assuming that the node with the value of x is unique.

void Print(BiTNode* b) //Output subtree with node x as root node
{
	if (b == NULL) return;
	else
	{
		printf("%c ", b->data);
		Print(b->lchild);
		Print(b->rchild);
	}
}

void Child(BiTNode* b,ElemType x) //Descendants of output x node
{
	if (b == NULL) return;
	else
	{
		if (b->data == x)
		{
			if(b->lchild!=NULL) Print(b->lchild);
			if(b->rchild!=NULL) Print(b->rchild);
		}
		Child(b->lchild, x);
		Child(b->rchild, x);
	}
}

Operation results

5. Copy the binary chain b1 into the binary chain b2.

void Copy(BiTNode* b1,BiTNode *&b2)
{
	if (b1 == NULL) b2 = NULL;
	else
	{
		b2 = (BiTNode*)malloc(sizeof(BiTNode));
		b2->data = b1->data;
		Copy(b1->lchild, b2->lchild);
		Copy(b1->rchild, b2->rchild);
	}
}

Operation results

6. Assuming that the binary tree adopts binary chain storage structure, calculate the number of nodes in the k-th layer of binary tree b.

  • Algorithm idea: Lnodenum(BiTNode *b,int k), H represents the node level referred to by b, and n is used to calculate the number of nodes in layer K. In the initial call, b is the root node pointer, h is 1, and n is assigned 0.
  • The following algorithm is obtained based on the idea of preorder traversal:
int n = 0; //Global variable, used to count the number of nodes at layer k
void Lnodenum(BiTNode* b, int h, int k)
{
	if (b == NULL) return; //Empty tree direct return
	else //Dealing with non empty trees
	{
		if (k == h) n++; //When the currently accessed node is in layer k, n increases by 1
		else if (h < k) //If the current node level is less than k, the left and right subtrees are processed recursively
		{
			Lnodenum(b->lchild, h + 1, k);
			Lnodenum(b->rchild, h + 1, k);
		}
	}
}

7. Find the number of leaf nodes on layer k in the binary tree.

int LevelCount(BiTNode* b, int k,int h)
{
	static int count = 0;
	if (b == NULL) return 0;
	else
	{
		if (b->lchild == NULL && b->rchild == NULL && k == h)
		{
			printf("%c ", b->data);
			count++;
		}
		LevelCount(b->lchild, k, h + 1);
		LevelCount(b->rchild, k, h + 1);
		return count;
	}
}

Operation results

8. A binary tree with n nodes is known and stored in order. Recursive and non recursive algorithms for traversing the nodes in the binary tree in advance are designed.

recursive algorithm

void PreOrder1(TreeNode t[], int i)
{
//The t [] array stores a binary tree (the size is maxsize), and the initial value of I is 1
	if (i < MaxSize)
	{
		if (t[i].value != '#')
		{
			printf("%c ", t[i].value); //Access root node
			PreOrder1(t, i * 2); //Traverse left subtree
			PreOrder1(t, i * 2 + 1); //Traversing right subtree
		}
	}
}
PreOrder1(t, 1);

non-recursive algorithm

void PreOrder2(TreeNode t[]) //Preordered non recursive traversal algorithm
{
	SqStack* st; //Define stack pointer st
	InitStack(st); //Initialize stack st
	int i = 1;
	Push(st, i);
	while(st->top>-1)
	{
		Pop(st, i); //Back up the node and access it
			printf("%c ", t[i].value);
			if (2 * i + 1 < MaxSize && t[2 * i + 1].value != '#') Push(st, 2 * i + 1); // Put the right child in the stack when there is one
			if (2 * i < MaxSize && t[2 * i].value != '#') Push(st, 2 * i); // Put the left child in the stack when there is one
		}
	DestroyStack(st); //Destroy stack
}

Operation results

9. Design an algorithm void findparent (bitnode b, char x, bitnode & p) to find the parent node p of the node with the specified value of X in binary tree b.

  • Algorithm idea: using the recursive method based on preorder traversal, first judge the root node, if it does not meet the requirements, and then find it in the left subtree; If not found, finally look in the right subtree.
void FindParent(BiTNode* b, ElemType x, BiTNode*& p)
{
	if (b != NULL)
	{
		if (b->data == x) p = NULL;
		else if (b->lchild != NULL && b->lchild->data == x) p = b;
		else if (b->rchild != NULL && b->rchild->data == x) p = b;
		else
		{
			FindParent(b->lchild, x, p);
			if (p == NULL) FindParent(b->rchild, x, p);
		}
	}
	else p = NULL;
}

Operation results

10. Establish the chain storage structure of binary tree (bracket representation)

  • Algorithm idea:
    ① If ch = '(': it means that the node p just created has child nodes, and it needs to be stacked as the top node of the stack in order to establish the relationship between it and its child nodes (if a node has just been created, and the subsequent character is not '(', it means that the node is a leaf child node and does not need to be stacked). Then start processing the left child of the node and set K = 1 (indicating that the node created later will be the left child node of the top node of the stack). ② If ch = ')': it means that the child with the top node as the root node has been created, and it will be returned to the stack.
    ③ If ch = ',': it means to start processing the right child node of the stack top node, and set K = 2 (it means that the node created later will be the right child node of the current stack top node).
    ④ Other situations: it can only be a single character, corresponding to a node value in the binary tree. You need to create a node p to store the node value. According to the K value, the relationship between it and the top node of the stack is established. When k=1, take node P as the left child of the top node of the stack; When k=2, node P is the right child of the top node of the stack.
void CreateBTree(BiTNode* &b,ElemType *str)
{
	BiTNode* St[MaxSize], * p; //St array as sequential stack
	int top = -1, j = 0, k; //Top is the stack top pointer
	ElemType ch;
	b = NULL; //Initially, the binary chain is empty
	ch = str[j];
	while (ch != '\0') //Cycle through every character in str
	{
		switch (ch)
		{
		case '(':top++; St[top] = p; k = 1; break; //Start processing left child node
		case ')':top--; break; //The subtree of the top node of the stack has been processed
		case ',':k = 2; break; //Start processing right child node
		default:p = (BiTNode*)malloc(sizeof(BiTNode)); //Create a node with p pointing to it
			p->data = ch; //Store node value
			p->lchild = p->rchild = NULL; //Both the left and right pointers are set to null
			if (b == NULL) b = p; //If the root node has not been established, the node referred to by p is regarded as the root node
			else //Binary tree root node established
			{
				switch(k)
				{
					case 1:St[top]->lchild = p; break; //Create a new node as the left child of the top node of the stack
					case 2:St[top]->rchild = p; break; //Create a new node as the right child of the top node of the stack
				}
			}
		}
		j++; //Continue scanning str
		ch = str[j];
	}
}

11. The bottom-up and right to left hierarchical traversal algorithm of binary tree is given.

  • Algorithm idea: using the original hierarchical traversal algorithm, the pointer of each node is put on the stack while leaving the queue. After all nodes are put on the stack, they are accessed successively from the top of the stack, which is the required algorithm.
void LevelOrder(BiTNode* b)
{
	BiTNode* p;
	SqStack* st;
	InitStack(st);
	SqQueue* qu;
	InitQueue(qu);
	enQueue(qu, b);
	printf("Top down, left to right level traversal:");
	while (!EmptyQueue(qu))
	{
		deQueue(qu, p);
		Push(st, p);
		printf("%c ", p->data);
		if (p->lchild != NULL) enQueue(qu, p->lchild);
		if (p->rchild != NULL) enQueue(qu, p->rchild);
	}
	printf("\n Bottom up, right to left level traversal:");
	for (int i = st->top; i >= 0; i--)
	{
		Pop(st, p);
		printf("%c ", p->data);
	}
}

Operation results

12. Assuming that the binary tree is stored in a binary chain storage structure, it is required to return the pointer of the first node in the subsequent sequence of binary tree b (without recursion and stack).

  • Algorithm idea: the first node in the post sequence of binary tree is the lowest left node in the left subtree. If the lowest left node has no left subtree but has a right subtree, the first node in the post sequence should be the lowest left node in the right subtree, and so on.
BiTNode* PostFirst(BiTNode* b)
{
	BiTNode* p = b;
	if (b != NULL)
		while (p->lchild != NULL || p->rchild != NULL)
		{
			while (p->lchild != NULL) p = p->lchild; //Find the leftmost lower node of node p first
			if (p->rchild != NULL) p = p->rchild; //If node p has a right child, turn to the right child
		}
	return p; //The first leaf node p found is the desired node
}

Operation results

13. Suppose a simple arithmetic expression containing only binary operators is stored in binary tree b in the form of binary chain, and write the algorithm for calculating the value of the arithmetic expression.

  • Algorithm idea: the arithmetic expression is represented by binary tree, and the root node is used to store operators. If the value of the sub expression represented by the left subtree and the right subtree can be obtained respectively, the final result of the expression can be calculated according to the requirements of the operator of the root node.
typedef struct node
{
	double val;
	char optr;
	struct node* lchild, * rchild;
}BTNode;
double compval(BTNode* b)
{
	double leftvalue, rightvalue, value;
	if (b != NULL)
	{
		if (b->lchild == NULL && b->rchild == NULL) return b->val; //Returns its value when it is a leaf node
		else
		{
			leftvalue = compval(b->lchild); //Find the value of the subexpression represented by the left subtree
			rightvalue = compval(b->rchild); //Find the value of the subexpression represented by the right subtree
			switch (b->optr)
			{
			case '+':value = leftvalue + rightvalue; break;
			case '-':value = leftvalue - rightvalue; break;
			case '*':value = leftvalue + rightvalue; break;
			case '/':if (rightvalue != 0) value = leftvalue / rightvalue;
					else exit(0); break;
			}
			return value;
		}
	}
	else return 0;
}

14. It is known that a binary tree is stored in a sequential structure, and the value of the nearest common ancestor node of the two nodes numbered i and j respectively is calculated.

  • Algorithm idea: 1) if I > J, the level of node I is greater than or equal to that of node j. The parent node of node I is node i/2. If i/2=j, node i/2 is the nearest common ancestor of the original nodes I and j, if i/2 ≠ J. Then let i=i/2, that is, take the parent node of the node as the starting point and continue to search by recursive method.
    1) If J > I, the level of node j is greater than or equal to that of node I. The parent node of node j is node j/2. If j/2=i, node j/2 is the nearest common ancestor node of original node i and j, if j/2 ≠ I. Then let = j/2, that is, take the parent node of the node as the starting point and continue to search by recursive method. Repeat the above process until their nearest common ancestor node is found.
int Layer(TreeNode t[], int i) //Find the level of node i
{
	return log2(i) + 1;
}

ElemType Com_Anc(TreeNode t[], int i, int j)
{
	if (t[i].value != '#' && t[j].value != '#'/ / node exists
	{
		while (i != j) //Two numbers do not cycle at the same time
		{
			if (i > j) i = i / 2; //Look up for i's ancestors
			else j = j / 2; //Look up for j's ancestors
		}
		return t[i].value;
	}
}

Operation results

15. Design an algorithm to find the number of nodes less than / greater than x in a given binary tree b by post order traversal.

int SmallThanNodes(BiTNode* b, ElemType x) //Find all nodes less than x
{
	if (b == NULL) return 0;
	else
	{
		int num1, num2, snum = 0;
		num1 = SmallThanNodes(b->lchild, x);
		num2 = SmallThanNodes(b->rchild, x);
		snum = num1 + num2;
		if (b->data < x)
		{
			printf("%c ", b->data);
			snum++;
		}
		return snum;
	}
}

int BigThanNodes(BiTNode* b, ElemType x) //Find all nodes greater than x
{
	if (b == NULL) return 0;
	else
	{
		int num1, num2, bnum = 0;
		num1 = BigThanNodes(b->lchild, x);
		num2 = BigThanNodes(b->rchild, x);
		bnum = num1 + num2;
		if (b->data > x)
		{
			printf("%c ", b->data);
			bnum++;
		}
		return bnum;
	}
}

Operation results

16. Find the minimum / maximum node value in binary tree b (preorder recursion).

void MinNode(BiTNode* b, ElemType& minnode)
{
	if (b == NULL) return;
	else
	{
		if (b->data < minnode) minnode = b->data;
		MinNode(b->lchild, minnode);
		MinNode(b->rchild, minnode);
	}
}

void MaxNode(BiTNode* b, ElemType& maxnode)
{
	if (b == NULL) return;
	else
	{
		if (b->data > maxnode) maxnode = b->data;
		MaxNode(b->lchild, maxnode);
		MaxNode(b->rchild, maxnode);
	}
}

ElemType minnode, maxnode;
minnode = maxnode = b->data;
MinNode(b, minnode);
MaxNode(b, maxnode);

Operation results

17. Find the maximum node value in a binary tree b, and the empty tree returns' 0 '(post order recursion).

ElemType MaxNode(BiTNode* b)
{
	ElemType max = b->data, max1;
	if (b != NULL)
	{
		if (b->lchild == NULL && b->rchild == NULL) return b->data; //When there is only one node
		else
		{
			if (b->data > max) max = b->data;
			if (b->lchild != NULL) max1 = MaxNode(b->lchild); //Traverse left subtree
			if (max1 > max) max = max1;
			if (b->rchild != NULL) max1 = MaxNode(b->rchild); //Traversing right subtree
			if (max1 > max) max = max1; //Find the maximum value
			return max;
		}
	}
	return '0';
}

ElemType MinNode(BiTNode* b)
{
	ElemType min = b->data, min1;
	if (b != NULL)
	{
		if (b->lchild == NULL && b->rchild == NULL) return b->data;
		else
		{
			if (b->data < min) min = b->data;
			if (b->lchild != NULL) min1 = MinNode(b->lchild);
			if (min1 < min) min = min1;
			if (b->rchild != NULL) min1 = MinNode(b->rchild);
			if (min1 < min) min = min1;
			return min;
		}
	}
	return '0';
}

Topics: C data structure Binary tree Visual Studio