- 设计求T的WPL的算法:
(1).给出二叉树结点的数据类型定义;
(2).给出C语言描述算法;
【1】:
typedef struct node
{ int weight;
struct node *left,*right; //指向结点左右子女的指针
}BiNode,*BiTree;
【2】:
int WPL=0;
void inorder(BiTree bt,level lv)
//bt是二叉树,lv是结点的层次,初值为1
{ if(bt)
{inorder (bt->left,lv+1); //中序遍历左子树
if(bt->left==null &&bt->right==null) //判断该结点是否为叶子
WPL+=(lv-1)*bt->weight; //累加结点带权路径长度
inorder(bt->right,lv+1);
}
}
【先序遍历】NLR(递归)
void PreOrder(BiTree T){
if(T!=NULL){
visit(T); //访问根结点
PreOrder(T->lchild); //递归遍历左子树
preOrder(T->rchild);
}
}
【中序遍历】LNR(递归)
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
【后序遍历】LRN(递归)
void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);
}
}
【先序非递归遍历】
void PreOrderTraverse(BiTree b){
InitStack(S);
BiTree p=b; //工作指针p
while(p||!IsEmpty(S)){
while(p){
Printf(“%c”,p->data); //先序先遍历结点
Push(S,p); //进栈保存
p=p->lchild;
}
if(!IsEmpty(S)){
p=Pop(S);
p=p->rchild;
}
}
}
【中序非递归遍历】
void InOrder(BiTree b){
InitStack(S);
BiTree p=b;
while(p||!IsEmpty(S)){ //栈不空或P不空时循环
if(p){ //根指针进栈,遍历左子树
Push(S,p); //每遇到非空二叉树先向左走
p=p->lchild;
}
else{ //根指针退栈,访问根结点,遍历右子树
Pop(S,p);
visit(b);
p=p->rchild; //再向右子树走
}
}
}
【后序非递归遍历】
1 void PostOrder(BiTree b){
2
3 InitStack(S);
4
5 BiTree p=b,r=NULL; //工作指针P,辅助指针r
6
7 while(p||!IsEmpty(S)){
8
9 //1.从根结点到最左下角的左子树都入栈
10
11 if(p){
12
13 Push(S,p);
14
15 p=p->lchild;
16
17 }
18
19 //2.返回栈顶的两种情况
20
21 else{
22
23 GetTop(S,p); //取栈顶,不是出栈!
24
25 //1)右子树还未访问,而且右子树不空,第一次栈顶
26
27 if(p->rchild&&p->rchild!=r)
28
29 p=p->rchild;
30
31 //2)右子树已经访问或为空,接下来出栈访问结点
32
33 else{
34
35 Pop(S,p);
36
37 Printf(“%c”,p->data);
38
39 r=p; //指向访问过的右子树根结点
40
41 p=NULL; //使p为空从而继续访问栈顶
42
43 }
44
45 }
【层次遍历】
void LevelOrder(BiTree T){
InitQueue(Q);
BiTree p;
EnQueue(Q,T); //将根结点入队
while(!IsEmpty(Q)){ //队列不空循环
DeQueue(Q,P); //对头元素出队
visit(p);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild); //左子树不空,则左子树入队列
if(p->rchild!=NULL)
EnQueue(Q,p->rchild); //右子树不空,则右子树入队列
}
设计一个算法,从大到小输出二叉排序树中所有其值不小于k 的关键字。
【分析】:
为了从大到小输出,先遍历右子树,再访问根结点,后遍历左子树。
【算法】:
void OutPut(BSTNode *bt,KeyType k){
if(bt==NULL)
return ;
if(bt->rchild!=NULL)
OutPut(bt->rchild,k); //递归输出右子树结点
if(bt->data>=k)
Printf(“%d”,bt->data); //只输出大于等于k的结点值
if(bt->lchild!=NULL)
OutPut(bt->lchild,k); //递归输出左子树的结点
}
【图的邻接矩阵存储结构定义】
#define MaxVertexNum 100 //顶点数目的最大值
typedef char VertextType; //顶点的数据类型
typedef int EdgeType; //带权图中边上权值的数据类型
typedef struct{
VertexType Vex[MaxVertexNum]; //顶点表
EdgeType Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表
int vexnum,arcnum; //图的当前顶点数和弧数
}MGraph;
【图的邻接表存储结构定义】
#define MaxVertexNum 100 //图中顶点数目的最大值
typedef struct ArcNode{ //边表结点
int adjvex; //该弧所指向的顶点的位置
struct ArcNode *next; //指向下一条弧的指针
//InfoType info; //网的边权值
}ArcNode;
typedef struct VNode{ //顶点表结点
VertextType data; //顶点信息
ArcNode *first; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{
AdjList vertices; //邻接表
int vexnum,arcnum; //图的顶点数和弧数
}ALGraph; //ALGraph是以邻接表存储的图类型
图的遍历:
【BFS算法】:
1 #define MaxSize 100;
2
3 bool visited[MaxSize]; //访问标记数组
4
5 void BFS(Graph G,int v){
6
7 ArcNode *p;
8
9 InitQueue(Q);
10
11 visit(v);
12
13 visited[v]=TRUE; //对v做已访问标记
14
15 Enqueue(Q,v);
16
17 while(!IsEmpty(Q)){
18
19 DeQueue(Q,v);
20
21 p=G->adjList[v].firstedge; //指针P指向当前顶点的边表链表头指针
22
23 while(p){
24
25 if(!visited[p->adjvex]){ //P所指向顶点如果未被访问
26
27 visit(p->adjvex);
28
29 visited[p->adjvex]=TRUE;
30
31 EnQueue(Q,p->adjvex); //这个顶点入队列
32
33 }
34
35 p=p->next; //p指向该顶点的下一条边
36
37 }
38
39 }
40
41 }
42
43 void BFSTraverse(Graph G){
44
45 for(i=0;i<G.vexnum;i++)
46
47 visited[i]=FALSE; //访问标记数组初始化
48
49 for(i=0;i<G.vexnum;i++){ //从0号顶点开始遍历
50
51 if(!visited[i]) //对每个连通分量调用一次BFS
52
53 BFS(G,i);f //vi未访问过,从vi开始BFS
54
55 }
56
57 }
【BFS算法求解单源最短路径问题】
void BFS_MIN_Distance(Graph G,int u){
//d[i]表示从u到i结点的最短路径
for(i=0;i<G.vexnum;++i)
d[i]=65535; //初始化路径长度
visited[u]=TRUE; d[u]=0;
EnQueue(Q,u);
while(!IsEmpty(Q)){ //BFS算法主过程
DeQueue(Q,u); //对头元素u出队
for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w))
if(!visited[w]){ //w为u的尚未访问的邻接顶点
visited[w]=TRUE; //设已访问标记
d[w]=d[u]+1; //路径长度加1
EnQueue(Q,w); //顶点w入队
}//if
}//while
}
【DFS算法】(递归)
1 #define MaxSize 100;
2
3 bool visited[MaxSize];
4
5 void DFS(Graph G,int v){
6
7 ArcNode *p;
8
9 visit(v);
10
11 visited[v]=TRUE; //设已访问标记
12
13 p=G->adjList[v].firstarc;
14
15 while(p!=NULL){ //没遍历完顶点的所有邻接顶点
16
17 if(!visited[p->adjvex]){ //如果该顶点没被访问
18
19 DFS(G,p->adjvex); //递归访问该顶点
20
21 }
22
23 p=p->nextarc; //看还有没有其他未访问的顶点
24
25 }
26
27 }
28
29 void DFSTraverse(Graph G){
30
31 int i;
32
33 for(i=0;i<G->vexnum;i++)
34
35 visited[i]=false;
36
37 for(i=0;i<G->vexnum;i++)
38
39 if(!visited[i])
40
41 DFS(G,i);
42
43 }
(非递归)邻接表存储
【DFS非递归算法】:
void DFS_Non_RC(AGraph &G,int v){
//从顶点v开始进行深度优先搜索,一次遍历一个连通分量的所有顶点
int w; //顶点序号
InitStack(S);
for(i=0;i<G.vexnum;i++)
visited[i]=FALSE; //初始化visited
Push(S,v); visited[v]=TRUE; //v入栈并置visited[v]
while(!IsEmpty(S)){
k=Pop(S); //栈中退出一个顶点
visit(v); //先访问,再将其子结点入栈
for(w=FirstNeighbor(G,k);w>=0;w=NextNeighbor(G,k,w))
//k所有邻接点
if(!visited[w]){ //未进过栈的顶点进栈
Push(S,w);
visited[w]=true; //作标记,以免再次入栈
}//if
}//while
}
【拓扑排序算法】:
1 bool TopologicalSort(Graph G){
2
3 //如果G存在拓扑排序,返回truel;否则返回false,这时G中存在环
4
5 InitStack(S);
6
7 for(int i=0;i<G.vexnum;i++)
8
9 if(indegree[i]==0)
10
11 Push(S,i); //将所有入度为0的顶点进栈
12
13 int count=0; //计数,记录当前已经输出的顶点数
14
15 while(!IsEmpty(S)){ //栈不空,则存在入度为0的顶点
16
17 Pop(S,i); //栈顶元素出栈
18
19 print[count++]=i; //输出顶点i
20
21 for(p=G.vertices[i].firstarc;p;p=p->nextarc){
22
23 //将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈S
24
25 v=p->adjvex;
26
27 if(!(- -indegree[v]))
28
29 Push(S,v); //入度为0,则入栈
30
31 }//for
32
33 }//while
34
35 if(count<G.vexnum)
36
37 return false; //排序失败,有向图中有回路
38
39 else
40
41 return true; //成功
42
43 }
【直接插入排序算法】
void InsertSort(ElemType A[],int n){
int i,j;
for(i=2;i<=n;i++) //依次将A[2]~A[n]插入到前面已排序序列
if(A[i].key<A[i-1].key){ //若A[i]的关键码小于其前驱,需将A[i]插入有序表
A[0]=A[i]; //复制为哨兵,A[0]不存放元素
for(j=i-1;A[0].key<A[j].key;--j) //从后往前查找待插入位置
A[j+1]=A[j]; //向后挪位
A[j+1]=A[0]; //复制到插入位置
}
}
【冒泡排序算法】:
void BubbleSort(ElemType A[],int n){
//将序列A中的元素按从小到大排序
for(i=0;i<n-1;i++){
flag=false; //表示本趟冒泡是否发生交换的标志
for(j=n-1;j>i;j--) //一趟冒泡过程
if(A[j-1].key>A[j].key){ //若为逆序
swap(A[j-1],A[j]);
flag=true;
}
if(flag==false)
return ; //本趟遍历后没有发生交换,说明表已经有序
}
}
【折半查找】:
int Binary_Search(SeqList L,ElemType key){
//在有序表L中查找关键字为key的元素,若存在返回其位置,
int low=0,high=L.TableLen-1,mid;
while(low<=high){
mid=(low+high)/2;
if(L.elem[mid]==key)
return mid;
else if(L.elem[mid]>key)
high=mid-1;
else
low=mid+1; //从后半部分继续查找
}
return -1;
}