树
非线性结构
非线性有层次
定义:
-
有且只有一个称为根节点
-
有若干个互不相交的子树,子树本身也是一个树
通俗的定义:
-
树是由节点和边组成
-
每一个节点只有一个父节点,但可以有多个子节点
-
根节点没有父节点
专业术语:
节点
子孙
深度:
从根节点到最底层节点的层数称为深度,根节点是第一层
叶子结点:没有子节点的节点
非终端节点:实际就是非叶子节点
度:子节点的个数,最大做整体
树的分类:
一般树:任意一个节点的子节点的个数都不受限制
二叉树:任意一个节点的子节点的个数最多两个,且子节点的位置不可更改
一般二叉树
满二叉树
完全二叉树
如果只是删除了满二叉树最底层最右边的连续若干个节点,这样形成的二叉树就是完全二叉树
森林:
n个互不相交的树的集合
树的存储
二叉树的存储
连续存储【完全二叉树】
链式存储
一般树的存储
森林的存储
先转化为二叉树再存储
孩子在左,兄弟在右
操作
树的遍历
先序遍历
递归思想
先访问根节点
再访问左节点
最后访问右节点
中序遍历
后序遍历
已知两种遍历序列求原始二叉树
通过先序和中序或者中序和后序可以
但先序和后序无法
#include<stdio.h>
#include<malloc.h>
struct BTNode
{
int date;
struct BTNode*pLchild;//左孩子
struct BTNode*pRchild;//右孩子
};
struct BTNode*CreatBTree();
void PreTraverseBTree(struct BTNode*pT);
void InTraverseBTree(struct BTNode*pT);
void postTraverseBTree(struct BTNode*pT);
int main(void)
{
struct BTNode* pT=CreatBTree();
PreTraverseBTree(pT);
InTraverseBTree(pT);
postTraverseBTree(pT);
return 0;
}
void PreTraverseBTree(struct BTNode*pT)
{
if(NULL!=pT)
{
//根左右
printf("%c\n",pT->date);
//代表整个左子树pT->pLchild
if(NULL!=pT->pLchild)
{
PreTraverseBTree(pT->pLchild);
}
if(NULL!=pT->pRchild)
{
PreTraverseBTree(pT->pRchild);
}
}
}
void InTraverseBTree(struct BTNode*pT)
{
if(NULL!=pT)
{
//根左右
printf("%c\n",pT->date);
//代表整个左子树pT->pLchild
if(NULL!=pT->pLchild)
{
PreTraverseBTree(pT->pLchild);
}
//根左右
printf("%c\n",pT->date);
if(NULL!=pT->pRchild)
{
PreTraverseBTree(pT->pRchild);
}
}
}
void postTraverseBTree(struct BTNode*pT)
{
if(NULL!=pT)
{
//根左右
printf("%c\n",pT->date);
//代表整个左子树pT->pLchild
if(NULL!=pT->pLchild)
{
PreTraverseBTree(pT->pLchild);
}
//根左右
if(NULL!=pT->pRchild)
{
PreTraverseBTree(pT->pRchild);
}
printf("%c\n",pT->date);
}
}
struct BTNode*CreatBTree(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->date='A';
pB->date='B';
pC->date='C';
pD->date='D';
pE->date='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);
bool QuickSort(int*a,int low,int high);
int main(void)
{
int a[6]={-2,1,0,-5,4,3};
QuickSort(a,0,5);//第二个元素表示第一个元素的下标,第二个元素表示最后一个元素的下标
for(int i=0;i<6;i++)
{
printf("%d",a[i]);
}
printf("\n");
return 0;
}
bool 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[high]=a[low];
}
a[low]=val;
return low;
}
并归排序
排序和查找的关系:
排序是查找的前提
排序是重点