树定义
专业定义:有且只有一个称为根的节点,有若干个互不相交的子树,这些子树的本身也是一棵树。
通俗的定义:树是由节点和边组成;每个节点只有一个父节点但可以有多个子节点;但有一个节点例外,该节点没有父节点,此节点称为根节点。
专业术语
节点 父节点 子节点 子孙 堂兄弟 深度
深度:从根节点到底层节点的层数称之为深度。根节点是第一层.
叶子节点:没有子节点的节点.
非终端节点:实际上就是非叶子节点.
度:子节点的个数称之为度.
树的分类
一般树:任意一个节点的子节点的个数都不受限制.
二叉树:任意一个节点的子节点的个数最多2个,且子节点的位置不可更改。
二叉树是有序树。
森林:n个互不相交的树的集合.
二叉树的分类
一般二叉树
满二叉树:在不增加树的层数的前提下,无法再多添加一个节点的二叉树就是满二叉树.
完全二叉树:如果只是删除满二叉树最底层、最右边的连续若干个节点,这样形成的二叉树就是完全二叉树.
满二叉树是完全二叉树的一个特例.
树的存储
二叉树的存储
连续存储【完全二叉树】
优点:查找某个节点的父节点和子节点
缺点:耗用内存空间过大.
一般树的存储
双亲表示法
求父节点方便----求下标,从0开始
孩子表示法
求子节点方便
双亲孩子表示法
求父节点和子节点都很方便
二叉树的表示法
把一个普通树转化程二叉树来存储.
具体转化方法:
设法保证任意一个节点的左指针域指向它的第一个孩子,
右指针域指向它的下一个兄弟.
只要能满足此条件,就可以把一个普通树转化为二叉树.
一个普通树转化为的二叉树,一定是没有右子树的。
森林的存储:
先把森林转化为二叉树,再存储二叉树.
#include <stdio.h>
#include <malloc.h>
/**
  *静态构建一个二叉树
  *2014/8/30
  */
struct BTNode * CreateBTree(void);
void PreTraverseBTree(struct BTNode * pT);
void InTraverseBTree(struct BTNode * pT);
void PostTraverseBTree(struct BTNode * pT);
typedef struct BTNode
{
	int data;
	struct BTNode * pLchild; //p是指针, L是左, child是孩子
	struct BTNode * pRchild;
};
int main(void)
{
	struct BTNode * pT = CreateBTree();
//	PreTraverseBTree(pT);
//	InTraverseBTree(pT);
	PostTraverseBTree(pT);
	
	return 0;
}
//后序遍历
void PostTraverseBTree(struct BTNode * pT)
{
	if(NULL != pT)
	{
		if(NULL != pT->pLchild)
		{
			PreTraverseBTree(pT->pLchild);
		}
		if(NULL != pT->pRchild)
		{
			PreTraverseBTree(pT->pRchild);
		}
		printf("%c\n", pT->data);  //输出跟元素
		
	}
	
}
//中序遍历
void InTraverseBTree(struct BTNode * pT)
{
	if(NULL != pT)
	{
		if(NULL != pT->pLchild)
		{
			PreTraverseBTree(pT->pLchild);
		}
	
		printf("%c\n", pT->data);  //输出跟元素
		if(NULL != pT->pRchild)
		{
			PreTraverseBTree(pT->pRchild);
		}
		
	}
	
}
//先序遍历
void PreTraverseBTree(struct BTNode * pT)
{
	if(pT != NULL)
	{
		printf("%c\n", pT->data);  //输出跟元素
		if(NULL != pT->pLchild)
		{
			PreTraverseBTree(pT->pLchild);
		}
		if(NULL != pT->pRchild)
		{
			PreTraverseBTree(pT->pRchild);
		}
		// pT->pLchild  可以代表整个左子树
	}
	/**
		伪算法
		先访问根节点;
		再先序遍历左子树;
		再先序遍历右子树.
	*/
}
//静态创建二叉树
struct BTNode * CreateBTree(void)
{
	struct BTNode * pA = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode * pB = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode * pC = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode * pD = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode * pE = (struct BTNode*)malloc(sizeof(struct BTNode));
	
	pA->data = 'A';
	pB->data = 'B';
	pC->data = 'C';
	pD->data = 'D';
	pE->data = 'E';
	pA->pLchild = pB;
	pA->pRchild = pC;
	pB->pLchild = pB->pRchild = NULL;
	pC->pLchild = pD;
	pC->pRchild = NULL;
	pD->pLchild = NULL;
	pD->pRchild = pE;
	pE->pLchild = pE->pRchild = NULL;
	return pA;  //根节点的地址
}
树的应用
树是数据库中数据组织一种重要形式。
操作系统子父进程的关系本身就是一棵树
面向对象语言中类的继承关系。
哈夫曼树。
排序和查找的关系
排序是查找的前提。
排序是重点。
/**
  *快速排序	
  *
  */
#include <stdio.h>
int FindPos(int *a, int low, int high);
void QuickSort(int *a, int low, int high);
int main(void)
{
	int a[6] = {2, 1, 0, 5, 4, 3};
	int i;
	//第二个参数代表第一个元素的下标
	//第三个参数代表最后一个元素的下标
	QuickSort(a, 0, 5);
	for(i=0; i<6; ++i)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	return 0;
}
void QuickSort(int *a, int low, int high)
{
	int pos;
	if(low < high)
	{
		pos = FindPos(a, low, high);
		QuickSort(a, low, pos-1);  //左边的一半
		QuickSort(a, pos+1, high); //右边的一半
	}
}
int FindPos(int *a, int low, int high)
{
	int val = a[low];
	while(low < high)
	{
		while(low < high && a[high] >= val)
		{
			--high;
		}
		a[low] = a[high];
		while(low < high && a[low] <= val)
		{
			++low;
		}
		a[low] = val;
	} //终止while循环之后, low和high一定是相等的
	return high;
}
原文地址:http://blog.csdn.net/u012301841/article/details/38946461