c语言实现数据结构--建立一颗二叉树

目录

建立一颗二叉树

二叉树的定义及性质

建立一颗二叉树代码

二叉树的遍历

先序遍历

 非递归

中序遍历

后序遍历

非递归 

层序遍历

递归方法


建立一颗二叉树

二叉树的定义及性质

二叉树的特点是一颗有序树,每个结点的度最大为2。从根结点开始,他的左孩子和右孩子也是一颗树的根结点,也就是这个结点的左子树和右子树

二叉树的分支有左右子树之分,而树的分支无左右子树之分。

两种特殊的二叉树:

满二叉树:深度为h且结点数为2的h次方-1的二叉树,在这种二叉树中,除最后一层全是叶子结点外,其余每一层上的各个结点都有左右孩子。

完全二叉树:深度为h,有n个结点的二叉树,当且仅当每个结点都与深度为h的满二叉树中编号从1到n的结点一一对应。满二叉树是完全二叉树的特殊形式。

完全二叉树具有的特点:

1.所有的叶子节点都在最下面两层,除最后一层外的各层组成的二叉树是一颗满二叉树

2.若某个结点有右孩子,则该结点必有左孩子

性质:

1.二叉树的第i层上的结点个数的最大值为2的i-1次方(i>=1)

2.深度为h的二叉树上的结点个数的最大值为2 的h次方-1,即深度为h的完全二叉树上的结点个数为为2 的h-1次方-1.

3.对任何一颗二叉树,若其终端结点数为n0,度为2的结点数为n2,则n0  = n2 + 1

4.含有n个结点的完全二叉树的深度为[㏒2n]+1

5.具有n个结点的完全二叉树的结点按层次编号(按从上到下。从左到右的方式连续编号),则对任一结点i有:

建立一颗二叉树代码

包括初始化以及销毁

typedef struct Node{
	int val;
	struct Node *lchild, *rchild;
}Node;
typedef struct tree{
	Node *root;
	int n;
}Tree;
//初始化结点
Node* GetNewNode(int val){
	Node *p = (Node*)malloc(sizeof(Node));
	p->val = val;
	p->rchild = p->rchild = NULL;
	return p; 
} 
//初始化一个树 
Tree*GetNewTree(){
	Tree*tree = (Tree*)malloc(sizeof(Tree));
	tree->n = 0;
	tree->root = NULL;
	return tree;
}
Node* insertNode(Node *root, int val){
	if(root == NULL)
		return GetNewNode(val);
	if(root->val == val)
		return root;
	else if(root->val > val)
		root->lchild = insertNode(root->lchild, val);
	else 
		root->rchild = insertNode(root->rchild, val);
	return root;
} 
//插入一个结点 
void insert(Tree*tree, int val){
	tree->root = insertNode(tree->root, val);
	tree->n++;
	return;
}
//销毁 
void clearNode(Node* node){
	if(node == NULL)
		return ;
	clearNode(node->lchild);
	clearNode(node->rchild);
	free(node);
	return ;
} 
void clearTree(Tree*tree){
	clearNode(tree->root);
	free(tree);
	return;
}

二叉树的遍历

分为前序中序后序遍历,这个前中后都是说的根节点,然后还有层序遍历

先序遍历

先访问根节点,先序遍历左子树,先序遍历右子树

递归方法简单而且好理解,但是对电脑内存栈需求量大

void p1(Node *node){
	if(node){
		cout << node->val;//先输出跟结点 
		p1(node->lchild);//遍历左子树 
		p1(node->rchild);//遍历右子树 
	}
} 

 非递归

//先序遍历的非递归算法利用栈的性质
void p_1(Tree *tree){
	Node *ro = tree->root;
	if(ro){
		stack<Node*>s;
		s.push(ro);//根节点入栈
		while(!s.empty()){
			while(s.top() && ro){//栈顶元素非空 
				cout << s.top()->val;
				ro = ro->lchild;
				s.push(ro);
			}
			s.pop();//空结点出栈 
			if(!s.empty()){
				s.pop();
				ro = ro->rchild; 
				s.push(ro);
			}
		} 
		
	}
	return ;
}

二叉树遍历就借用了c++STL里面的一部分

中序遍历

void p1(Node *node){
	if(node){ 
		p1(node->lchild);//遍历左子树 
        cout << node->val;//先输出跟结点
		p1(node->rchild);//遍历右子树 
	}
} 

中序遍历的非递归几乎和先序一样,会一个就相当于都会了

后序遍历

void p1(Node *node){
	if(node){
		p1(node->lchild);//遍历左子树 
		p1(node->rchild);//遍历右子树
		cout << node->val;//先输出跟结点 
	}
} 

非递归 

//后序遍历的非递归算法利用栈的性质
void p_1(Tree *tree){
	Node *ro = tree->root;
	if(ro){
		stack<Node*>s;
		s.push(ro);//根节点入栈
		while(!s.empty()){
			while(s.top() && ro){//遍历左子树 
				//cout << s.top()->val;
				ro = ro->lchild;
				s.push(ro);
			}
			s.pop();//空结点出栈 
			if(!s.empty()){//遍历右子树+
				cout << a.top()->val; 
//				s.pop();
//				ro = ro->rchild; 
//				s.push(ro);
				if(ro->rchild){
					s.push(ro->rchild);//右子树根节点入栈 
				} 
				else{//左右子树遍历结束,访问根结点 
					s.pop();
					cout << ro->val;
					while(!s.top() && s.top() && ro->rchild == ro){
						//若访问的结点是其双亲结点的右孩子,则双亲出栈 
						s.pop();
						cout << ro->val;
					} 
					if(s.empty()){//使栈顶结点的右孩子入栈 
						s.push(ro->rchild);
					}
					
				}
			}
		} 
		
	}
	return ;
}

层序遍历

递归方法

void level(Node *node){
	Node *p = node;
	queue<Node*> q;
	q.push(p);
	while(!q.empty()){
		q.pop();
		cout << p->val;
		if(p->lchild)
			q.push(p->lchild);
		if(p->rchild)
			q.push(p->rchild);
	}
	return;
}

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值