汇总一些数据结构解题方法。。。= =,
P44 6.65
由二叉树的前序序列M和中序序列N构造二叉链表
代码
1 Bitree Create(char *M, char *N, int m1, int m2, int n1, int n2)
2 {
3 BiTree p;
4 if (m1 > m2 || n1 > n2)
5 return NULL;
6 p = malloc(sizeof(BiTNode));
7 p->data = M[m1];
8 temp = n1;
9 while (N[temp] != M[m1])
10 temp++;
11 p->lchild = Create(M, N, m1 + 1, m1 + temp - n1, n1, temp - 1);
12 p->rchild = Create(M, N, m1 + temp - n1 + 1, m2, temp + 1, n2);
13 return p
14 }
P44 6.68
由按层次输入的结点数列和结点的度构造树的孩子兄弟链表
代码
1 BiTree Search(char c, BiTree T) //辅助函数,用于根据结点元素查找其在树中的地址
2 {
3 BiTree p = NULL, q = NULL;
4 if (T)
5 {
6 if (T->data == c)
7 return T;
8 else
9 {
10 p = Search(c, T->chi);
11 q = Search(c, T->bro);
12 if (p)
13 return p;
14 else
15 {
16 if (q)
17 return q;
18 else
19 return NULL;
20 }
21 }
22 }
23 return NULL;
24 }
25
26 BiTree Create(char *M, int *N, int length) //M为结点序列,N为相应的度数组,length为数组长度
27 {
28 BiTree T, p;
29 int i = 0, k = 0, j, n;
30 while (k <= length - 1)
31 {
32 if (N[i] != 0)
33 {
34 j = 0;
35 n = N[i];
36 while (j <= n)
37 {
38 if (j == 0)
39 {
40 if (i == 0)
41 {
42 p = malloc(sizeof(BiTNode));
43 T = p;
44 p->data = M[k];
45 p->bro = NULL;
46 }
47 else
48 {
49 p = Search(M[i], T);
50 k--;
51 }
52 p->chi = malloc(sizeof(BiTNode));
53 p = p->chi;
54 k++;
55 j++;
56 }
57 else
58 {
59 p->data = M[k];
60 p->chi = NULL;
61 if (j != n)
62 p->bro = malloc((sizeof(BiTNode));
63 else
64 p->bro = NULL;
65 p = p->bro;
66 k++;
67 j++;
68 }
69 }
70 }
71 i++;
72 }
73 return T;
74 }
P49 7.27
代码
1 visited[0,1,...,G.vexnum - 1] = 0;
2 int Judge(int v1, int v2, ALGraph G, int k)
3 {
4 if (v1 == v2 && k == 0)
5 return 1;
6 if (v1 != v2 && k == 0)
7 return 0;
8 visited[v1] = 1;
9 for (p = G.vertices[v1].firstarc; p; p = p->nextarc)
10 {
11 if (visited[p->adjvex] == 0)
12 {
13 if (Judge(p->adjvex, v2, k - 1))
14 return 1;
15 }
16 }
17 visited[v1] = 0;
18 return 0;
19 }
P152 5.6
按照书上用MFSet实现对集合的划分比较麻烦,还得另外编写一些函数进行相关操作,于是采用另一种方法,定义一个字符数组MFSet[30],初始化阶段令字符内各个值从0递增至29,在之后把归并为同一个子集的字符的值设为同样的数值即可(通过Merge函数)。
随后输出为文件采用的是fprintf函数,必须注意的是每次写入完一组数据之后得将文件指针fp恢复到追加模式,否则只有最后的结果输出到文件。
端点应以A开始,且保证个数不超过26。
代码
#include <stdio.h>
#include <stdlib.h>
typedef struct arc //定义带权边,i、j分别代表边的两个端点,duty是权
{
char i, j;
int duty;
}arc;
char MFSet[30]; //字符数组辅助之后的集合划分
void Initial(int n) //初始化字符数组,使之表示独立的一个元,即每个子集只有一个元素
{
int i;
for (i = 0; i < 30; i++)
{
MFSet[i] = i;
}
}
void Merge(int e,int f, int n) //将不同的子集归并
{
int i;
for (i = 0; i < n; i++)
{
if (MFSet[i] == e)
MFSet[i] = f;
}
}
arc* InitArc() // 创建带权边数组
{
int i, arcn, n, x, y;
arc *p, *q;
printf("Input the length of the arc array:\n"); //带权边的数目
scanf("%d", &arcn);
printf("Input the number of the node:\n"); //端点数目
scanf("%d", &n);
getchar();
q = p = (arc*)malloc(sizeof(arc) * (arcn + 1));
p->i = n; p->j = n; p->duty = arcn;
p++;
for (i = 0; i < arcn; i++, p++)
{
printf("Input the arc:\n");
scanf("(%c,%c) %d", &p->i, &p->j, &p->duty);
getchar(); //消除输入完毕之后缓存区中回车字符的影响
}
return q;
}
arc* MinDutyArc(arc *p, int arcn, int n) //查找最小权值的边
{
int i, min = 100;
arc *q;
for (i = 0; i < arcn; i++, p++)
{
if (p->duty < min && MFSet[p->i - 'A'] != MFSet[p->j - 'A']) //不仅判断权值的大小,还判断是否隶属于同一个子集
{
q = p;
min = p->duty;
}
}
Merge(MFSet[q->i - 'A'], MFSet[q->j - 'A'], n); //将两个有公共端点的子集归并
return q;
}
void main()
{
FILE *fp;
int i, arcn, n, t;
arc *p, *q;
p = InitArc();
arcn = p->duty;
t = n = p->i;
p++;
fp = fopen("result.txt", "w"); //创建result.txt文件
fprintf(fp, "The result is:\n\n ARC DUTY\n");
fp = fopen("result.txt", "a"); //更改读取方式为追加
Initial(n);
while (t > 1)
{
q = MinDutyArc(p, arcn, n);
fprintf(fp, "(%c,%c) %d\n", q->i, q->j, q->duty);
fp = fopen("result.txt", "a"); //更改读取方式为追加,没有这个的话文件末尾只有最后的一组结果
t--;
}
fclose(fp);
}