二叉树的遍历
二叉树的遍历分成三种,按照根节点的访问先后分为:
先序遍历:先访问根节点,然后访问左子树, 最后访问右子树。
中序遍历:先访问左子树,然后访问根节点, 最后访问右子树。
后续遍历:先访问左子树,然后访问右子树, 最后访问根节点。
以上图为例,先序遍历的结果为ABC,中序遍历的结果为BAC,后序遍历的结果为BCA
先序遍历:ABDFCEGHI
中序遍历:BFDACHGIE
后序遍历:FDBHIGECA
前序:从A开始向左子树B再至C,访问B时出现了B的右子树D,访问C时出现了右子树E。然而排序是ABDFCE,因为B和C是A的子树,而B的访问顺序在C之前,余下的顺序同理
中序:从B开始,将B□D视作一个二叉树,则顺序是□BD,访问D,将DF□视作二叉树,则访问顺序为FD□。B的所有分支访问完毕,故返回A。所以顺序是BFDA,余下同理
后序:从B开始,将B□D视为一个二叉树,顺序为□DB。访问D,将DF□视作一个二叉树,顺序为F□D。F无子树,则开始返回,顺序为FDB。A的右子树同理
课后习题,答案为B
由前序遍历知道,A是根节点
则根据中序遍历,知道HBDF是左子树,EKCG是右子树
然后在根据前序遍历 BHFD,知道B是左子树的根节点 ,再根据中序遍历知道H是左子树,DF是右子树,同理F是根,D是左子树。
A的右子树同理
图(的很少一部分)
在学习广搜时接触到了一丢丢,记录一下
图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合。
无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示。对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D};边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}
有向图:若从顶点Vi到Vj的边是有方向的,则成这条边为有向边,也称为弧(Arc)。用有序对(Vi,Vj)标示,Vi称为弧尾,Vj称为弧头。如果任意两条边之间都是有向的,则称该图为有向图。
有向图G2中,G2=(V2,{E2}),顶点集合(A,B,C,D),弧集合E2={<A,D>,{B,A},<C,A>,<B,C>}
c语言中的qsort函数
其声明在stdlib.h文件中,是根据二分法写的,其时间复杂度为n*log(n)
功能: 使用快速排序例程进行排序
头文件:stdlib.h
用法: void qsort(void* base,size_t num,size_t width,int(__cdeclcompare)(const void,const void*));
参数: 1 待排序数组,排序之后的结果仍放在这个数组中
2 数组中待排序元素数量
3 各元素的占用空间大小(单位为字节)
4 指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)
qsort要求提供一个自己定义的比较函数。比较函数使得qsort通用性更好,有了比较函数qsort可以实现对数组、字符串、结构体等结构进行升序或降序排序。
int num[100];
int cmp_int(const void* _a , const void* _b) //参数格式固定
{
int* a = (int*)_a; //强制类型转换
int* b = (int*)_b;
return *a -*b; //默认从小到大排序
}
qsort(num,100,sizeof(num[0]),cmp_int);
比较字符串时应写为:return strcmp(a,b);
特别注意,double型的返回值应写为:return *a > *b ? 1 : -1;
因为要是使用像整型那样相减的话,如果是两个很接近的数则可能返回一个很小的小数(大于-1,小于1),而cmp的返回值是int型,因此会将这个小数返回0,系统认为是相等,失去了本来存在的大小关系。