{
if (num < 10)
{
return num
}
int iTmp = num
int iRoot = 0
while (iTmp > 0)
{
iRoot = iRoot + iTmp % 10
iTmp /= 10
}
return GetNumberRoot(iRoot)
}
int main()
{
int iRoot = GetNumberRoot(123456)
printf("root:%d\n",iRoot)
return 0
}
表达式树是树结构的一个经典应用。常见的表达式:3+5*7+2为中缀表达式。
这里,我实现一种转换算法,那就是先把中缀式子转化为一棵树,然后使用不同的遍历遍历方式得到不同的表达式
【注】(仅仅给出没有括号时的代码,为了简化字符串处理,我没有使用字符串,而是使用了字符,因此不支持两位的数字算式)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct string_node {
char tag //定义字符
struct string_node *left
struct string_node *right
struct string_node *parent
}
struct string_node *gen_sub_tree(char*str, int len)
{
struct string_node *root
int i = 0
for (i = 0i <leni++) {
struct string_node *node = (struct string_node*)calloc(1, sizeof(structstring_node))
node->tag =str[i]
if(isdigit(str[i])) {
if (i != 0) {//运算由左至右,除了第一个 *** 作数,其它全部为右 *** 作数,高优先级的会处在树的旁支
root->right = node
node->parent = root
}
root = node
} else if((str[i] == 'x') || (str[i] == '/')) {
//处理乘除运算符
struct string_node *temp_root = NULL, *temp_parent = NULL
if (root->parent &&(root->parent->tag == '+' || root->parent->tag == '-')) {
temp_parent = root->parent
temp_root = root
} else if(root->parent) {
temp_parent =root->parent->parent
temp_root = root->parent
} else {
temp_root = root
}
node->parent = temp_parent
if (temp_parent)
temp_parent->right = node
node->left = temp_root
temp_root->parent = node
root = node
} else if (str[i] == '+' || str[i] == '-') {
//处理加减运算符
struct string_node *temp_root =NULL, *temp_parent = NULL
if (root->parent &&root->parent->parent &&(root->parent->tag == 'x' || root->parent->tag == '/')) {
temp_root =root->parent->parent
} else if (root->parent&&!root->parent->parent){
temp_root = root->parent
} else {
temp_root = root
}
node->left = temp_root
temp_root->parent = node
root = node
}
}
//找到树根,返回调用者
while (root->parent) {
root = root->parent
}
return root
}
int main(int argc, char **argv)
{
struct string_node *root
char str[40] ={'1','+','0','+','2','x','5','+','3','x','4','x','2', '-', '7'}
root = NULL
root = gen_sub_tree(str, 100)
print_result(root)
return 0
}
//输出结果
void print_result(struct string_node*p)
{
if(p != NULL) {
//此为后缀表达式,根据printf的位置不同可以得到不同的X缀表达式
print_result(p->left)
print_result(p->right)
printf("%c\n", p->tag)
}
}
【】下面考虑加上括号时的情况,由于号优先级最高,而且还不是像运算符那样结合 *** 作数的字符,因此把括号括住的成分单独作为一个 *** 作数比较好,这样就可以递归的实现了。,只需要加入对’(‘和’)’的解析即可喽,递归调用gen_sub_tree即可。以下为加入括号处理的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct string_node {
char tag //定义字符
struct string_node *left
struct string_node *right
struct string_node *parent
}
struct string_node *gen_sub_tree(char*str, int len)
{
struct string_node *root
int i = 0
for (i = 0i <leni++) {
struct string_node *node = (struct string_node*)calloc(1, sizeof(structstring_node))
node->tag =str[i]
if(isdigit(str[i])) {
if (i != 0) {//运算由左至右,除了第一个 *** 作数,其它全部为右 *** 作数,高优先级的会处在树的旁支
root->right = node
node->parent = root
}
root = node
} else if((str[i] == 'x') || (str[i] == '/')) {
//处理乘除运算符
struct string_node *temp_root = NULL, *temp_parent = NULL
if (root->parent &&(root->parent->tag == '+' || root->parent->tag == '-')) {
temp_parent = root->parent
temp_root = root
} else if(root->parent) {
temp_parent =root->parent->parent
temp_root = root->parent
} else {
temp_root = root
}
node->parent = temp_parent
if (temp_parent)
temp_parent->right = node
node->left = temp_root
temp_root->parent = node
root = node
} else if (str[i] == '+' || str[i] == '-') {
//处理加减运算符
struct string_node *temp_root =NULL, *temp_parent = NULL
if (root->parent &&root->parent->parent &&(root->parent->tag == 'x' || root->parent->tag == '/')) {
temp_root =root->parent->parent
} else if (root->parent&&!root->parent->parent){
temp_root = root->parent
} else {
temp_root = root
}
node->left = temp_root
temp_root->parent = node
root = node
}
}
//找到树根,返回调用者
while (root->parent) {
root = root->parent
}
return root
}
int main(int argc, char **argv)
{
struct string_node *root
char str[40] ={'1','+','0','+','2','x','5','+','3','x','4','x','2', '-', '7'}
root = NULL
root = gen_sub_tree(str, 100)
print_result(root)
return 0
}
//输出结果
void print_result(struct string_node*p)
{
if(p != NULL) {
//此为后缀表达式,根据printf的位置不同可以得到不同的X缀表达式
print_result(p->left)
print_result(p->right)
printf("%c\n", p->tag)
}
}
#include <stdio.h>#include <stdlib.h>
#define STACK_MAX_SIZE 30
#define QUEUE_MAX_SIZE 30
#ifndef elemType
typedef char elemType
#endif
/************************************************************************/
/* 以下是关于二叉树 *** 作的11个简单算法*/
/************************************************************************/
struct BTreeNode{
elemType data
struct BTreeNode *left
struct BTreeNode *right
}
/* 1.初始化二叉树 */
void initBTree(struct BTreeNode* *bt)
{
*bt = NULL
return
}
/* 2.建立二叉树(根据a所指向的二叉树广义表字符串建立) */
void createBTree(struct BTreeNode* *bt, char *a)
{
struct BTreeNode *p
struct BTreeNode *s[STACK_MAX_SIZE]/* 定义s数组为存储根结点指针的栈使用 */
int top = -1/* 定义top作为s栈的栈顶指针,初值为-1,表示空栈 */
int k/* 用k作为处理结点的左子树和右子树,k = 1处理左子树,k = 2处理右子树 */
int i = 0/* 用i扫描数组a中存储的二叉树广义表字符串,初值为0 */
*bt = NULL/* 把树根指针置为空,即从空树开始建立二叉树 */
/* 每循环一次处理一个字符,直到扫描到字符串结束符\0为止 */
while(a[i] != '\0'){
switch(a[i]){
case ' ':
break /* 对空格不作任何处理 */
case '(':
if(top == STACK_MAX_SIZE - 1){
printf("栈空间太小!\n")
exit(1)
}
top++
s[top] = p
k = 1
break
case ')':
if(top == -1){
printf("二叉树广义表字符串错误!\n")
exit(1)
}
top--
break
case ',':
k = 2
break
default:
p = malloc(sizeof(struct BTreeNode))
p->data = a[i]
p->left = p->right = NULL
if(*bt == NULL){
*bt = p
}else{
if( k == 1){
s[top]->left = p
}else{
s[top]->right = p
}
}
}
i++ /* 为扫描下一个字符修改i值 */
}
return
}
/* 3.检查二叉树是否为空,为空则返回1,否则返回0 */
int emptyBTree(struct BTreeNode *bt)
{
if(bt == NULL){
return 1
}else{
return 0
}
}
/* 4.求二叉树深度 */
int BTreeDepth(struct BTreeNode *bt)
{
if(bt == NULL){
return 0 /* 对于空树,返回0结束递归 */
}else{
int dep1 = BTreeDepth(bt->left) /* 计算左子树的深度 */
int dep2 = BTreeDepth(bt->right) /* 计算右子树的深度 */
if(dep1 >dep2){
return dep1 + 1
}else{
return dep2 + 1
}
}
}
/* 5.从二叉树中查找值为x的结点,若存在则返回元素存储位置,否则返回空值 */
elemType *findBTree(struct BTreeNode *bt, elemType x)
{
if(bt == NULL){
return NULL
}else{
if(bt->data == x){
return &(bt->data)
}else{ /* 分别向左右子树递归查找 */
elemType *p
if(p = findBTree(bt->left, x)){
return p
}
if(p = findBTree(bt->right, x)){
return p
}
return NULL
}
}
}
/* 6.输出二叉树(前序遍历) */
void printBTree(struct BTreeNode *bt)
{
/* 树为空时结束递归,否则执行如下 *** 作 */
if(bt != NULL){
printf("%c", bt->data) /* 输出根结点的值 */
if(bt->left != NULL || bt->right != NULL){
printf("(")
printBTree(bt->left)
if(bt->right != NULL){
printf(",")
}
printBTree(bt->right)
printf(")")
}
}
return
}
/* 7.清除二叉树,使之变为一棵空树 */
void clearBTree(struct BTreeNode* *bt)
{
if(*bt != NULL){
clearBTree(&((*bt)->left))
clearBTree(&((*bt)->right))
free(*bt)
*bt = NULL
}
return
}
/* 8.前序遍历 */
void preOrder(struct BTreeNode *bt)
{
if(bt != NULL){
printf("%c ", bt->data) /* 访问根结点 */
preOrder(bt->left)/* 前序遍历左子树 */
preOrder(bt->right) /* 前序遍历右子树 */
}
return
}
/* 9.前序遍历 */
void inOrder(struct BTreeNode *bt)
{
if(bt != NULL){
inOrder(bt->left)/* 中序遍历左子树 */
printf("%c ", bt->data) /* 访问根结点 */
inOrder(bt->right)/* 中序遍历右子树 */
}
return
}
/* 10.后序遍历 */
void postOrder(struct BTreeNode *bt)
{
if(bt != NULL){
postOrder(bt->left) /* 后序遍历左子树 */
postOrder(bt->right) /* 后序遍历右子树 */
printf("%c ", bt->data) /* 访问根结点 */
}
return
}
/* 11.按层遍历 */
void levelOrder(struct BTreeNode *bt)
{
struct BTreeNode *p
struct BTreeNode *q[QUEUE_MAX_SIZE]
int front = 0, rear = 0
/* 将树根指针进队 */
if(bt != NULL){
rear = (rear + 1) % QUEUE_MAX_SIZE
q[rear] = bt
}
while(front != rear){ /* 队列非空 */
front = (front + 1) % QUEUE_MAX_SIZE/* 使队首指针指向队首元素 */
p = q[front]
printf("%c ", p->data)
/* 若结点存在左孩子,则左孩子结点指针进队 */
if(p->left != NULL){
rear = (rear + 1) % QUEUE_MAX_SIZE
q[rear] = p->left
}
/* 若结点存在右孩子,则右孩子结点指针进队 */
if(p->right != NULL){
rear = (rear + 1) % QUEUE_MAX_SIZE
q[rear] = p->right
}
}
return
}
/************************************************************************/
/*
int main(int argc, char *argv[])
{
struct BTreeNode *bt/* 指向二叉树根结点的指针 */
char *b/* 用于存入二叉树广义表的字符串 */
elemType x, *px
initBTree(&bt)
printf("输入二叉树广义表的字符串:\n")
/* scanf("%s", b)*/
b = "a(b(c), d(e(f, g), h(, i)))"
createBTree(&bt, b)
if(bt != NULL)
printf(" %c ", bt->data)
printf("以广义表的形式输出:\n")
printBTree(bt) /* 以广义表的形式输出二叉树 */
printf("\n")
printf("前序:") /* 前序遍历 */
preOrder(bt)
printf("\n")
printf("中序:") /* 中序遍历 */
inOrder(bt)
printf("\n")
printf("后序:") /* 后序遍历 */
postOrder(bt)
printf("\n")
printf("按层:") /* 按层遍历 */
levelOrder(bt)
printf("\n")
/* 从二叉树中查找一个元素结点 */
printf("输入一个待查找的字符:\n")
scanf(" %c", &x) /* 格式串中的空格跳过空白字符 */
px = findBTree(bt, x)
if(px){
printf("查找成功:%c\n", *px)
}else{
printf("查找失败!\n")
}
printf("二叉树的深度为:")
printf("%d\n", BTreeDepth(bt))
clearBTree(&bt)
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)