数据结构——树与二叉树

一、树

1、树的定义

     树是一种非线性的数据结构,是递归的。

2、树的基本术语

  	 ①结点的度:结点拥有子树的个数或者分支的个数。例如,A结点有3棵子树,A结点的度为3。
  	 ②树的度:树中结点度的最大值。
     ③叶子结点:树中结点度为0的结点。
	 ④森林:互不相交的树的集合。

二、二叉树

1、定义

    ①每个结点至多有两个子树;
     ②二叉树是有序树,左右子树不能颠倒。

2、性质

           ①在二叉树第i层上有2^(i-1)个结点
           ②深度为k的二叉树至多有2^k--1个结点
           ③非空二叉树上叶子结点数等于双分支结点数加1
           ④具有n个结点的完全二叉树的深度为log2(n)取下界+1

3、二叉树的存储结构

 1、链式存储结构
typedef struct BTNode{
	char data;  //结点数据
	struct BTNode *lchild; //左孩子结点 
	struct BTNode *rchild; 
}; 

4、二叉树的遍历

1、先序遍历递归
   void preorder(BTNode *p){
	if(p!=NULL){
		cout<<p->data;
		preorder(p->lchild);
		preorder(p->rchild);
	}
} 

例题:在一棵二叉链表为存储结构的二叉树中,查找data值等于key的结点是否存在。存在返回1,否则返回0.


int search(BTNode *p,int key){
	if(p!=NULL){
		if(p->data == NULL) return 0;
		if(p->data == key)        //先序遍历查找
		return 1;
		else{
			search(p->lchild,key);
			search(p->rchild,key);
		}
	}
}
2、中序遍历
void inorder(BTNode *p){
	if(p!=NULL){
		inorder(p->lchild);
		cout<<p->data;
		inorder(p->rchild);
	}
}

例题:中序遍历第k个结点的值(二叉链表存储)

void trave(BTNode *p,int k){
	if(p!=NULL){
		trave(p->lchild,k);
		++n;
		if(n==k){
			cout<<p->data;
			return ;
		}
		trave(p->rchild,k);
	}
}
3、后序遍历
void postorder(BTNode *p){
	if(p!=NULL){
		postorder(p->lchild);
		postorder(p->rchild);
		cout<<p->data;
	}
}

例题:表达式(a-(b+c))*(d/e)求表达式的值

int comp(BTNode *p){
	int a,b;
	if(p!=NULL){
		if(p->lchild!=NULL && p->rchild!=NULL){
			a = comp(p->lchild);
			b = comp(p->rchild);
			return op(a,b,p->data);
		}
		else return p->data-'0';
	}else{
		return 0;
	}
}
int op(int op_left,int op_right,char c){
	if(c == '+')
	   return op_left+op_right;
	if(c == '-')
	   return op_left-op_right;
	if(c == '*')
	   return op_left*op_right;
	if(c == '/')
	   return op_left/op_right;
	return 0;
}

例题2:求二叉树的高度(左子树或者右子树的最大值)

int getDepth(BTNode *p){
	if(p==NULL) return 0;
	int leftTree,rightTree;
	leftTree = getDepth(p->lchild);
	rightTree = getDepth(p->rchild);
	return (leftTree > rightTree?leftTree:rightTree) +1; //最大值加1因为从0开始 
}
4、层序遍历
int level(BTNode *p){
	//定义一个循环队列
	BTNode *que[maxSize];
	int front,rear;
	front = rear =0;
	BTNode *q;
	if(p!=NULL){
		rear = (rear+1)%maxSize;
		que[rear] = p;
		while(front!=rear){
			front = (front+1)%maxSize;
			q = que[front];
			cout<<q->data;
			if(q->lchild!=NULL){
				rear = (rear+1)%maxSize;
				que[rear] = q->lchild;
			}
			if(q->rchild!=NULL){
				rear = (rear+1)%maxSize;
				que[rear] = q->rchild;
			}
		}
	} 
}

例题:求二叉树的宽度(具有结点数最多的那一层上的结点个数)

typedef struct{
	BTNode *p;
	int lno;  //层号 
}Wt;
int maxNode(BTNode *b{
	//定义一个循环队列
	Wt que[maxSize];
	int front,rear;
	front = rear =0;
	int Lno=0;
	BTNode *q;
	if(b!=NULL){
		rear = (rear+1)%maxSize;
		que[rear].p = b;
		que[rear].lno = 1;
		while(front!=rear){
			front = (front+1)%maxSize;
			q = que[front].p;
			Lno = que[front].lno;
			if(q->lchild!=NULL){
				rear = (rear+1)%maxSize;
				que[rear].p = q->lchild;
				que[rear].lno = Lno+1;
			}
			if(q->rchild!=NULL){
				rear = (rear+1)%maxSize;
				que[rear].p = q->rchild;
				que[rear].lno = Lno+1;
			}
		}
			//得出最大层Lno;
		int max = 0;
		int n;
		for(int i=0;i<Lno;i++){
			n=0;
			for(int j=0;j<rear;j++){
			if(que[j].lno == i)
			 n++;
			 if(max<n)
			 max = n;
			}
		}
		return max; 
	}
}

二叉树深度优先遍历

其实就是先中后序遍历的非递归

//先序遍历非递归
void preorderNonrecursion(BTNode *bt){
	if(bt!=NULL){
		//定义一个栈 
		BTNode *stack[maxSize];
		int top = -1;
		BTNode *p;
		stack[++top] = bt;
		while(top!=-1){
			p = stack[top--];
			cout<<p->data;
			if(p->rchild!=NULL){                     //注意先右子树后左子树
				stack[++top] = p->rchild;
			}
			if(p->lchild!=NULL){
				stack[++top] = p->lchild;
			}
		}
	}
}
//后序遍历的非递归就是先序遍历过程中对左右子树交换(逆后序遍历),然后在逆序输出
void postorderNonrecursion(BTNode *bt){
	BTNode *stack1[maxSize]; int top1 = -1;
	BTNode *stack2[maxSize]; int top2 = -1;
	BTNode *p;
	stack1[++top1] = bt;
	while(top1!=-1){
		p = stack[top1--];
		stack2[++top2] = p;
		if(p->lchild!=NULL){
			stack2[++top2] = p->lchild;
		}
		if(p->rchild!=NULL){
			stack2[++top2] = p->rchild;
		}
	}
	while(top2!=-1)
	{
		 p = stack2[top2--];
		 cout<<p->data;
	}
}
//中序遍历非递归
void inorderNonrecursion(BTNode *bt){
	if(bt!=NULL){
		BTNode *stack[maxSize]; int top = -1;
		BTNode *p;
		p = bt;
		while(top!=-1 || p!=NULL){
			while(p!=NULL){
				stack[++top] = p;
				p = p->lchild;
			}
			if(top!=-1){
				p = stack[top--];
				cout<<p->data;
				p = p->rchild;
			}
		}
	}
}

线索二叉树

二叉树的线索化可以提高遍历的执行效率,线索二叉树可以把栈省略掉。因为线索化后近似于一个线性结构,分支结构的遍历就变成了近似于线性结构的遍历。

//线索二叉树结点定义
typedef struct TBTNode{
	char data;
	int ltag,rtag;
	struct TBTNode *lchild;
	struct TBTNode *rchild;
};
//中序线索化 pre 为p的前驱结点,初始为NULL 即TBTNode *pre = NULL;
void createInThread(TBTNode *root){
	TBTNode *pre = NULL;
	if(root!=NULL){
		InThread(root,pre);
		pre->rchild = NULL;
		pre->rtag = 1;
	}
} 
void InThread(TBTNode *p,TBTNode *&pre){
	if(p!=NULL){
		InThread(p->lchild,pre);
		if(p->lchild==NULL){
			p->lchild = pre;
			p->ltag = 1;
		}
		if(pre!=NULL && pre->rchild==NULL){
			pre->rchild = p;
			pre->rtag = 1;
		}
		pre = p;
		InThread(p->rchild,pre);
	}
}
//中序线索遍历
//1、以p为根的中序线索二叉树中序序列下的第一个节点
TBTNode *First(TBTNode *p){
	while(p->ltag==0)
	  p = p->lchild;
	  return p;
} 
//2、结点p的后继
TBTNode *Next(TBTNode *p){
	if(p->rtag==0)
	  return First(p->rchild);
	else
	  return p->rchild;
} 
//3、遍历
void inorder(TBTNode *root){
	TBTNode *p = First(root);
	
	for(p;p!=NULL;p=Next(p)){
		cout<<p->data;
	}
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值