1. 基本概念
结点的度 :树上任一结点所拥有的子树的数目称为该树的度。
叶子:度为0的结点称为叶子或终端结点。
结点的层次:从根开始算起,根的层次为1,其余结点的层次为其双亲的层次加1.
树的高度 : 一棵树中所有结点层次数的最大值称为该树的高度或深度。
有序树: 若树中各结点的子树从左到右是有次序的,不能互换,称为有序树。
遍历(TraverseTree(T))
2. 二叉树中 no = n2 + 1 (两层的满二叉树)
S = n0 + n1 + n2 + n3 + ... + nk; [结点总数]
S-1 = 0*n0 + 1*n1+ 2*n2 +.... + k*nk; [枝杈数目,枝杈通过孩子双亲关系产生]
3. 含有n个结点的完全二叉树的深度为[log2(n)] +1 (此处为下取整,将2代入可证)
4. 完全二叉树,没有虚拟结点,从顺序存储中可以看出(顺序表下标从 1 开始存储,表头下标为 0)。
5. 树的遍历(图是遍历深度和广度优先搜索)
先序遍历 preorder(BinTree BT) ; 中序遍历 inorder(BinTree BT) ; 后序遍历 postorder(BinTree BT)
void preorder(BinTree BT)
{
if (bt != NULL)
{
visit(bt);
preorder(bt -> lchild);
preorder(bt -> rchild);
}
}
// 非递归遍历实现
void PreOrder(BinTree BT)
{
BinTree p;
LKStk *LS;
if ( t == NULL ) return;
InitStack( LS );
p = t;
while( p != NULL || EmptyStack(LS)) //循环条件是当前指针或栈至少有一个不为空
{
if (p != NULL)
{
Visit(p->data); // 访问结点的数据
Push(LS,p); // 将当前指针压入栈中
p = p ->lchild; // 将指针指向p的左孩子
}
else
{
p = Gettop(LS); // 取栈顶元素
Pop(LS); // 出栈
p = p -> rchild; // 指针指向它的右孩子
}
} // end of while
}
void levelorder(BinTree bt)
{
LkQue Q;
InitQueue(&Q);
if (bt != NULL)
{ EnQueue(&Q,bt);
while(!EmptyQueue(Q))
{ p = GetHead(&Q);
outQueue(&Q);
visit(p);
if (p -> lchild != NULL) EnQueue(&Q, p -> lchild);
if (p -> rchild != NULL) EnQUeue(&Q, p -> rchild);
}// end of while
}// end of if
}
6. 树的应用判定树 --- 哈夫曼树
生成步骤
1)按照概率或者键值从小到大有序排列
2)按照原键值优先的原则,从序列中取出最小的和次小的进行两两结合。
3)最终生成的判定树满足 左孩子比右孩子小的特点。
哈夫曼编码 左0右1.
1. 基本概念 P130
图结构中结点之间的邻接关系可以是任意的。
G= (V,E)
边集和点集都是G的子集的G'是G的子图。
生成树:一个连通图的生成树,是含有该连通图的全部顶点的一个极小连通子图。(少一个边或者弧,图就不连通了。)
强连通分量:有向图的极大强连通子图称为强连通分量。(连通情况最好的)(McCabe复杂度模型 m-n+2p)
如果G的一个子图G’的边数大于n-1,则G’中一定有环。
图的存储形式有 邻接矩阵、邻接表、十字链表和邻接多重表。
路径,路径长度
回路: 第一个顶点和最后一个顶点相同的路径称为回路或环。
简单回路:除了第一个顶点和最后一个顶点外,其余顶点不重复的回路。
// 邻接矩阵的建立
void CreateGraph(Graph *g)
{
int i,j,n,e,w;
char ch;
scanf("%d %d", &n, &e);
g -> vexnum = n ;
g -> arcnum = e ;
for (i = 0 ;i < g -> vexnum; i++)
{ scanf("%c",&ch);
g -> vexs[i] = ch;
}
for (i = 0 ;i < g -> vexnum; i++)
for (j = 0 ;j < g -> vexnum; j++)
g -> arcs[i][j] = MAX_INT;
for (k = 0 ;k < g -> arcnum; k++)
{
scanf("%d %d %d" ,&i ,&j ,&w );
g -> arcs[i][j] = w;
g -> arcs[j][i] = w;
}
}
2. 邻接表
表头结点 (vertex,firstarc) ; 表结点(adjvex,nextarc); 带权图表结点(adjvex, weight, nextarc)
通过邻接表获得图的出度和入度。
出度,表头结点后面的表结点的数目;入度:结点标签在表结点中出现的次数。
逆邻接表
3. 邻接矩阵
有边或弧相连,arcs[ i ][ j ] = [ 1 | weight ];
无边或弧相连,arcs[ i ][ j ] = [ MAX_INT | ∞]
4. 图的遍历
深度优先搜索和广度优先搜索都 适用于有向图和无向图。
5. 最小生成树
Prim ( 贪吃蛇,吞并结点,寻找邻近的权重最小的边)
Kruskal (捡柴火,找权重最小的边,以不形成环为原则)
6. 单源最短路径
动态规划法,从一个顶点出发,通过不断计算各个顶点到源顶点的距离,吞并权重之和最小的顶点入点集,直至点集为全集.
图P150,出过课后题
7. 拓扑序列
入度为0的顶点先写, 表达式 vi1, vi2,vi3, ... ...
时间复杂度为 O(n+e)
1. 基本概念
查找表示由同一类型的数据元素构成的集合。
静态查找表 顺序表(ASL=(n+1)/2),有序表(二分查找(ASL=log2(n+1)-1),索引查找(ASL = (1/2)*(n/s + s)-1 两次顺序查找)
动态查找表 二叉排序树 (左小右大,根的比较次数为1;O(n) 和O(log2(n)));散列表(除留余数法生成散列地址;解决冲突:线性探测,二次探测,链地址法(解决“堆积”))
2. 散列表的基本概念
数据元素的键值和存储位置之间建立的对应关系H称为散列函数。
用键值通过散列函数获取存储位置的这种存储方式构造的存储结构称为散列表,这一映射过程称为散列。
解决的问题:1. 构造均匀的散列函数(数字分析法,除留余数法,平方取中法,基数转换法 ); 2. 如何解决冲突(线性探测,二次探测法,链地址法,多重散列法,公共溢出区法)。