数据结构--第六天

--树

        -树的基本概念

树结构通常用来储存逻辑关系为“一对多”的数据,例如:

上图的这些元素具有的就是 "一对多" 的逻辑关系,例如元素A同时和B、C、D有关系,元素D同时和A、H、I、J有关系等。 观察这些元素之间的逻辑关系会发现,它们整体上像一棵倒着的树,这也是将存储这些元素的结构起名为“树”的原因

        tips:树型结构可以保证数据的插入、删除、修改的速度

        -树的定义

          1. 树是由节点构成

          2. 树中除根节点,每一个节点都只有一个父节点,但是可以有多个子节点

          3. 根节点没有父节点

        -树中的专业术语

          节点:树结构存储的各个元素称为节点,例如:父节点,子节点,叶子节点

          节点的度:一个节点拥有子树的个数,就称为该节点的度

          叶子节点:没有子节点的节点,称为叶子节点

          边:一个节点到另一个节点的距离

          树的深度:树中结点的层数,根节点默认为第一层

          有序树: 如果一棵树中各个节点左子树和右子树的位置不能交换,那么这棵树就称为有序树

          无序树: 如果一棵树中各个节点左子树和右子树的位置可以交换,那么这棵树就称为无序树

          空树: 指没有任何节点的树,连根节点都没有

        -树的分类

           一般树:任意节点的子节点的个数不受限制,则称为一般树

           二叉树任意一个节点的子节点个数最多是2个

           森林:由多个树共同组成一片森林

        -二叉树的特性

           1.二叉树和链表一样,也是动态数据结构

            其结构体格式:

                struct Node{

                    datatype_t data;

                    struct Node* left;

                    struct Node* right;

                }

           2.二叉树具有唯一的根节点

           3.二叉树具有天然的递归结构(每个节点的左、右子树也是二叉树)

          满二叉树

                1>叶子节点出现在二叉树的最底层,除叶子节点之外的其他节点都有俩个子节点

                2>一个层数为k的满二叉树的总节点数为:2^k-1

                3>第i层上节点数为:2^(i-1) 

                4>一个层数为k的满二叉树的叶子节点个数(也就是最后一层)为:2^(k-1)

           完全二叉树

                概念:按照树的结构从上到下,从左到右依次将元素排列成树的形状

                性质:

                  1>根节点没有父节点

                  2>除根节点之外的任意节点(i)的父节点的索引为:(i-1)/2

                  3>任意节点的左子节点的的索引为:2*i+1

                  4>任意节点的右子节点的的索引为:2*i+2

        -二叉树的遍历

           二叉树的遍历是指从根结点触发,按照某种次序访问二叉树中所有节点,使得每个节点被访问且仅被访问一次

           四种常用遍历思想为:

                前序遍历:根节点-->左子树-->右子树

                中序遍历:左子树-->根节点-->右子树

                后序遍历:左子树-->右子树-->根节点

                层次遍历:只需按层次遍历即可

        -树示例代码

           main.c
#include "tree.h"

void menu(){
	printf("--------------------------------\n");
	printf("1.create tree\n");
	printf("2.preorder tree\n");
	printf("3.midorder tree\n");
	printf("4.suffixorder tree\n");
	printf("show complete binary tree array\n");
	printf("0.exit\n");
	printf("--------------------------------\n");
}

int main(){
	int select;
	node_t* root=NULL;
	do{
		menu();
		printf("请选择:");
		scanf("%d",&select);
		switch(select){
			case 1:
				while(getchar()!='\n');
				create_tree2(&root);
				break;
			case 2:
				printf("-------------------pre traversal----------------------\n");
				pre_traversal(root);
				putchar('\n');
				break;
			case 3:
				printf("-------------------middle traversal----------------------\n");
                                middle_traversal(root);
                                putchar('\n');
                                break;
			case 4:
				printf("-------------------suf traversal----------------------\n");
                                suf_traversal(root);
                                putchar('\n');
                                break;
			case 5:
				printf("-------------------level traversal----------------------\n");
                                level_traversal(root);
                                putchar('\n');
				break;
			case 0:
				printf("退出成功!\n");
				free(root);
				root=NULL;
				exit(EXIT_FAILURE);
		}
	}while(1);
	return 0;
}
        tree.c
#include "tree.h"


//创建树的方法
void create_tree2(node_t** p_root){
	//创建一个节点
	char c;
        scanf("%c",&c);
	if(c=='#'){
                return; 
        }
	node_t* p_node=(node_t*)malloc(sizeof(node_t));
	if(NULL==p_node){
		printf("malloc failure\n");
		return;
	}
	p_node->data=c;
	create_tree2(&(p_node->left));
	create_tree2(&(p_node->right));
	*p_root=p_node;
}

node_t* create_tree(){
	//创造节点
	printf("input character:");
	char c;
	scanf("%c",&c);
	if(c=='#'){
		return NULL;
	}
	node_t* p_node=(node_t*)malloc(sizeof(node_t));
	if(NULL==p_node){
		printf("malloc failure.\n");
		return NULL;
	}
	p_node->data=c;
	//创建左子树
	p_node->left=create_tree();
	//创建右子树
	p_node->right=create_tree();
	return p_node;
}
//前序遍历
void pre_traversal(node_t* root){
	//递归终止条件
	if(NULL==root){
		return;
	}
	//递归操作
	printf("%-3c",root->data);
	pre_traversal(root->left);
	pre_traversal(root->right);
}
void middle_traversal(node_t* root){                          
        //递归终止条件
        if(NULL==root){                                    
                return;                                    
        }
        //递归操作
        middle_traversal(root->left);
	printf("%-3c",root->data);
        middle_traversal(root->right);                        
}
void suf_traversal(node_t* root){
        //递归终止条件
        if(NULL==root){
                return;
        }
        //递归操作
        suf_traversal(root->left);
        suf_traversal(root->right);
	printf("%-3c",root->data);
}

void level_traversal(node_t* root){
	if(NULL==root){
		return;
	}
	//创建队列
	linkednode_t* queue=NULL;
	linkedlist_init(&queue);
	//1.将头节点入队
	linkedlist_insert_tail(queue,root);
	while(!linkedlist_is_empty(queue)){
		//2.出队
		node_t* node=linkedlist_remove_head(queue);
		printf("%-3c",node->data);
		//3.分别判断左右子树是否为空
		if(node->left!=NULL){
			linkedlist_insert_tail(queue,node->left);
		}
		if(node->right!=NULL){
			linkedlist_insert_tail(queue,node->right);
		}
		
	}
}
        tree.h
#ifndef _HEAD_COMPLETE_BT_H__
#define _HEAD_COMPLETE_BT_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include "linkedlist.h"

extern void create_tree2(node_t**);
extern void pre_traversal(node_t*);
extern void middle_traversal(node_t*);
extern void suf_traversal(node_t*);
extern void level_traversal(node_t*);
extern node_t* create_tree();


#endif
        linkedlist.c
#include "linkedlist.h"

void linkedlist_init(linkednode_t** p_head){                                         
        linkednode_t* p_node = (linkednode_t*)malloc(sizeof(linkednode_t));        
        if(p_node==NULL){                                        
                printf("malloc failure:%s\n",strerror(errno));   
                return;                                    
        }                                                        
        memset(p_node,0,sizeof(linkednode_t));                                                              
        p_node->next = NULL; 
	*p_head = p_node;	
}

// 添加的方法
bool linkedlist_insert_tail(linkednode_t* p_head,node_t* data){
	//将data添加到链表的尾部
	// 1、封装成节点
	linkednode_t* p_node = (linkednode_t*)malloc(sizeof(linkednode_t));
	if(p_node==NULL){
		printf("malloc failure:%s\n",strerror(errno));
		return false;
	}
	memset(p_node,0,sizeof(linkednode_t));
	p_node->data = data;
	p_node->next = NULL;
	// 1、找到链表的尾部
	linkednode_t* tail = p_head;
	while(tail->next!=NULL){
		tail= tail->next;
	}
	// 2、进行挂接
	tail->next=p_node;
	return true;
}

bool linkedlist_is_empty(linkednode_t* head){
	return head == NULL || head->next==NULL;
}

node_t* linkedlist_remove_head(linkednode_t* head){
	if(linkedlist_is_empty(head)){
		return NULL;
	}else{
		linkednode_t* delnode = head->next;
		head->next = head->next->next;
		return delnode->data;	
	}
}
        输出结果

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值