6-1 线性表元素的区间删除

1
2
3
4
5
6
7
8
9
10
List Delete(List L, ElementType minD, ElementType maxD) {
int i, p = 0;
for (i = 0; i <= L->Last; i++) {
if (L->Data[i] <= minD || L->Data[i] >= maxD) {
L->Data[p++] = L->Data[i];
}
}
L->Last = p - 1;
return L;
}

6-2 有序表的插入

1
2
3
4
5
6
7
8
9
10
void ListInsertSort(SqList *L, DataType x) {
int i;
int temp = 1;

for (i = 0; L->items[i] < x; i++) {
temp++;
}

ListInsert(L, temp, x);
}

6-3 合并两个有序数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void merge(int *a, int m, int *b, int n, int *c) {
int i, j, k;
while (i < m && j < n) {
if (a[i] < b[j])
c[k++] = a[i++];
else
c[k++] = b[j++];
}
while (i < m) {
c[k++] = a[i++];
}
while (j < n) {
c[k++] = b[j++];
}
}

6-4 顺序表操作集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
List MakeEmpty() {
List list;
list = (List) malloc(sizeof(struct LNode));
list->Last = -1;
return list;
}

Position Find(List L, ElementType X) {
int i;
for (i = 0; i < MAXSIZE; i++) {
if (L->Data[i] == X)
return i;
}
return ERROR;
}

bool Insert(List L, ElementType X, Position P) {
int i;

if (L->Last == MAXSIZE - 1) {
printf("FULL");
return false;
}

if (P < 0 || P > L->Last + 1) {
printf("ILLEGAL POSITION");
return false;
}

for (i = L->Last; i >= P; i--) {
L->Data[i + 1] = L->Data[i];
}
L->Data[P] = X;
L->Last++;
return true;

}

bool Delete(List L, Position P) {
int i;

if (P < 0 || P > L->Last) {
printf("POSITION %d EMPTY", P);
return false;
}

for (i = P; i < L->Last; i++) {
L->Data[i] = L->Data[i + 1];
}
L->Last--;

return true;
}

6-5 递增的整数序列链表的插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List Insert(List L, ElementType X) {
List p, s;
p = L;
s = (List) malloc(sizeof(struct Node));
s->Data = X;

while (p->Next && p->Next->Data < X) {
p = p->Next;
}
s->Next = p->Next;
p->Next = s;

return L;
}

6-6 删除单链表偶数节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
struct ListNode *createlist() {
int m;
struct ListNode *p, *s, *l;
p = (struct ListNode *) malloc(sizeof(struct ListNode));

scanf("%d", &m);
if (m == -1)
return NULL;
p->data = m;
p->next = NULL;
s = p;

while (1) {
scanf("%d", &m);
if (m == -1)
break;
l = (struct ListNode *) malloc(sizeof(struct ListNode));
l->data = m;
l->next = NULL;
s->next = l;
s = l;
}
return p;

}

struct ListNode *deleteeven(struct ListNode *head) {
struct ListNode *p = NULL, *s = NULL;

while (head && head->data % 2 == 0) {
p = head;
head = head->next;
free(p);
}
if (head == NULL)
return NULL;
s = head;
while (s->next) {
if (s->next->data % 2 == 0)
s->next = s->next->next;
else
s = s->next;
}
return head;
}

6-7 逆序数据建立链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct ListNode *createlist() {
int m;
struct ListNode *head, *p;
head = (struct ListNode *) malloc(sizeof(struct ListNode));
head->next = NULL;

while (1) {
scanf("%d", &m);
if (m == -1)
break;
p = (struct ListNode *) malloc(sizeof(struct ListNode));
p->next = head->next;
p->data = m;
head->next = p;
}
return head->next;
}

6-8 求链表的倒数第m个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ElementType Find(List L, int m) {
int i;
PtrToNode p, s;
p = s = L;

for (i = 0; i < m; i++) {
p = p->Next;
if (!p)
return ERROR;
}
while (p) {
s = s->Next;
p = p->Next;
}

return s->Data;
}

6-9 两个有序链表序列的合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
List Merge( List L1, List L2 )
{
List pa,pb,pc;
pa=L1->Next;
pb=L2->Next;
List L=(List)malloc(sizeof(List));
pc=L;

while(pa&&pb)
{
if(pa->Data>pb->Data)
{
pc->Next=pb;
pb=pb->Next;
}
else{
pc->Next=pa;
pa=pa->Next;
}
pc=pc->Next;
}

if(pa)
pc->Next = pa;
if(pb)
pc->Next = pb;
L1->Next=NULL;
L2->Next=NULL;

return L;
}

6-10 二叉树的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void InorderTraversal(BinTree BT) {//中序遍历
if (BT) {
InorderTraversal(BT->Left);
printf(" %c", BT->Data);
InorderTraversal(BT->Right);
}
}

void PreorderTraversal(BinTree BT) {//先序遍历
if (BT) {
printf(" %c", BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
}

void PostorderTraversal(BinTree BT) {//后序遍历
if (BT) {
PostorderTraversal(BT->Left);
PostorderTraversal(BT->Right);
printf(" %c", BT->Data);
}
}

void LevelorderTraversal(BinTree BT) {
BinTree B[100];//结构体数组
BinTree T;
int i = 0, j = 0;
if (!BT)return;//树为空,返回
if (BT)//不为空
{
B[i++] = BT;//根节点入队
while (i != j)//队列不空
{
T = B[j++];//出队
printf(" %c", T->Data);
if (T->Left) B[i++] = T->Left;
if (T->Right) B[i++] = T->Right;
}
}
}

6-11 二叉树的非递归遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void InorderTraversal( BinTree BT ){//中序遍历
BinTree T=BT;
Stack S =CreateStack();
while(T||!IsEmpty(S)){
while(T!=NULL){
Push(S,T);
T=T->Left;
}
T=Pop(S);
printf(" %c",T->Data);
T=T->Right;
}
}
void PreorderTraversal( BinTree BT ){//先序遍历
BinTree T=BT;
Stack S =CreateStack();
while(T||!IsEmpty(S)){
while(T!=NULL){
Push(S,T);
printf(" %c",T->Data);
T=T->Left;
}
T=Pop(S);
T=T->Right;
}
}
void PostorderTraversal( BinTree BT ){//后序遍历
BinTree T=BT;
Stack S =CreateStack();
while(T||!IsEmpty(S)){
while(T!=NULL){
T->flag=0;
Push(S,T);
T=T->Left;
}
T=Peek(S);
if(T->flag==0){
T->flag++;
T=T->Right;
}
else{
T=Pop(S);
printf(" %c",T->Data);
T=NULL;
}
}
}

6-12 求二叉树高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int GetHeight(BinTree BT) {
int lNum, rNum, Height;
if (BT) {
lNum = GetHeight(BT->Left);
rNum = GetHeight(BT->Right);
if (lNum > rNum)
Height = lNum;
else
Height = rNum;
return Height + 1;
} else {
return 0;
}
}

6-13 邻接矩阵存储图的深度优先遍历

1
2
3
4
5
6
7
8
9
10
void DFS(MGraph Graph, Vertex V, void (*Visit)(Vertex)) {
Vertex i;
Visit(V);
Visited[V] = true;
for (int i = 0; i < Graph->Nv; i++) {
if (Graph->G[V][i] == 1 && !Visited[i]) {
DFS(Graph, i, Visit);//进行递归
}
}
}

6-14 邻接表存储图的广度优先遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void BFS(LGraph Graph, Vertex S, void (*Visit)(Vertex)) {
Visited[S] = true;//标记起始点
Visit(S);
int queue[1000], front = 0, rear = 0;
queue[rear++] = S;//起始点入队列
PtrToAdjVNode temp;//temp就代表当前点的邻接点的下标
while (front < rear) {//队伍不为空
temp = Graph->G[queue[front++]].FirstEdge;
while (temp) {
int p = temp->AdjV;//把temp中的下标提取出来
if (!Visited[p]) {//如果p点没有被标记的话
Visited[p] = true;
Visit(p);
queue[rear++] = p;//储存在队列中
}
temp = temp->Next;//指向下一个邻接点
}
}
}

7-1 一元多项式的乘法与加法运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct LNode *List;

struct LNode {
ElementType coe;//系数
ElementType exp;//指数
List Next;//下一个节点
};

void Insert(List L, ElementType coe, ElementType exp);//插入
List Multi(List p1, List p2);//乘法
List Plus(List p1, List p2);//加法
int compare(List p1, List p2);//比较系数大小

int main() {
List p1, p2;
List p;
int num1, num2, coe, exp;
int i;
p1 = (List) malloc(sizeof(struct LNode));
p2 = (List) malloc(sizeof(struct LNode));
p1->Next = NULL;
p2->Next = NULL;

scanf("%d", &num1);
for (i = 0; i < num1; i++) {
scanf("%d %d", &coe, &exp);
Insert(p1, coe, exp);
}
scanf("%d", &num2);
for (i = 0; i < num2; i++) {
scanf("%d %d", &coe, &exp);
Insert(p2, coe, exp);
}
//乘法运算
p = Multi(p1->Next, p2->Next);
while (p) {
if (p->Next != NULL) {
printf("%d %d ", p->coe, p->exp);//非最后一个节点,不换行打印,后接空格
} else {
printf("%d %d\n", p->coe, p->exp);//最后一个节点,换行打印
}
p = p->Next;
}
//加法运算
p = Plus(p1->Next, p2->Next);
if (p) {
while (p) {
if (p->Next != NULL) {
printf("%d %d ", p->coe, p->exp);
} else {
printf("%d %d\n", p->coe, p->exp);
}
p = p->Next;
}
} else {//防止出现p1,p2抵消为零的情况
printf("0 0\n");
}
return 0;
}

/**
* 向链表中添加元素
* @param L 需要添加的链表
* @param coefficient 系数
* @param exponent 指数
*/
void Insert(List L, ElementType coe, ElementType exp) {
List s, p;
p = L;

while (p->Next)//找到最后一个节点
p = p->Next;

s = (List) malloc(sizeof(struct LNode));
s->Next = NULL;
s->coe = coe;
s->exp = exp;

p->Next = s;
}

/**
* 两个多项式相乘
* @param p1 代表多项式1的链表
* @param p2 代表多项式2的链表
* @return p 相乘后生成的新链表
*/
List Multi(List p1, List p2) {
List p, p1a, p2a, s;
int flag = 1;
p = (List) malloc(sizeof(struct LNode));
p->Next = NULL;
p1a = p1;

while (p1a) {
p2a = p2;//确保p1多项式中的每一项可以与p2多项式中的每一项分别相乘
s = (List) malloc(sizeof(struct LNode));
s->Next = NULL;

while (p2a) {//与p2多项式中的每一项分别相乘
Insert(s, p1a->coe * p2a->coe, p1a->exp + p2a->exp);
p2a = p2a->Next;
}
s = s->Next;

if (flag == 1) {
p = p->Next;
/*
* 如果是p1第一项与p2每一项相乘,那么先将链表p向后移一位,将头结点屏蔽
* 因为默认初始化的P1头结点有默认的exp = 0,coe = 0,这两个数据是多余的
* 如果不后移,那么头结点默认的数值0将会一直尾随整个乘法运算,导致最后的结果后面多两个0 0
*/
flag = 0;

}
p = Plus(p, s);//相加,确保同类项合并
p1a = p1a->Next;
free(s);
}

return p;
}

/**
* 比较两多项式指数大小
* @param p1 代表多项式1的链表
* @param p2 代表多项式2的链表
* @return 返回值为0时表示两指数相同,可以进行加法运算
*/
int compare(List p1, List p2) {
if (p1->exp > p2->exp)
return 1;//p1指数大
else if (p1->exp < p2->exp)
return -1;//p1指数小
else
return 0;//指数相同
}

/**
* 两个多项式相加
* @param p1 代表多项式1的链表
* @param p2 代表多项式2的链表
* @return p 相加后生成的新链表
*/
List Plus(List p1, List p2) {
List p, p1a, p2a;
int temp;
p = (List) malloc(sizeof(struct LNode));
p->Next = NULL;
p1a = p1;
p2a = p2;

while (p1a && p2a) {
temp = compare(p1a, p2a);
//判断指数大小,同指数才可以运算
switch (temp) {
case 1:
//当前p1a的指数大,将当前p1a的数据放入新链表
Insert(p, p1a->coe, p1a->exp);
p1a = p1a->Next;//p1a向后移动,p2a不改变
break;
case -1:
//当前p2a的指数大,将当前p2a的数据放入新链表
Insert(p, p2a->coe, p2a->exp);
p2a = p2a->Next;//p2a向后移动,p1a不改变
break;
case 0:
//指数相同,进行运算
if ((p1a->coe + p2a->coe) == 0) {
//系数为0,数据不放入新链表,直接将p1a和p2a后移
p1a = p1a->Next;
p2a = p2a->Next;
} else {
//数据放入新链表,p1a和p2a后移
Insert(p, p1a->coe + p2a->coe, p2a->exp);
p1a = p1a->Next;
p2a = p2a->Next;
}
break;
default:
break;
}
}
while (p1a) {
//p1a的项数多,将剩余项放入链表
Insert(p, p1a->coe, p1a->exp);
p1a = p1a->Next;
}
while (p2a) {
//p2a的项数多,将剩余项放入链表
Insert(p, p2a->coe, p2a->exp);
p2a = p2a->Next;
}
p = p->Next;
return p;
}

7-2 符号配对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <stdio.h>
#include <stdlib.h>

#define Maxsize 105
typedef struct StackRecord *Stack;
struct StackRecord {
int top;
char *array;
};

Stack creat();//创建空栈
int cheekEmpty(Stack s);//判断栈是否为空
void push(Stack s, char x);//添加新元素
void pop(Stack s);//删除
char top(Stack s);//取出

char a[100];
char str[200];

int main() {
int i, j = 0, flag = 0;
char ch;
Stack s = creat();

while (gets(str)) {
if (str[0] == '.' && !str[1])
break;
for( i=0; str[i]; i++){
if(str[i]=='('||str[i]=='['||str[i]=='{'||str[i]==')'||str[i]=='}' ||str[i]==']')
a[j++]=str[i];
else if(str[i]=='/'&&str[i+1]=='*'){
a[j++]='<';
i++;
}else if(str[i]=='*'&&str[i+1]=='/'){
a[j++]='>';
i++;
}
}
}

for (i = 0; i < j; i++) {
if (a[i] == '(' || a[i] == '[' || a[i] == '{' || a[i] == '<') {
push(s, a[i]);
} else if (a[i] == ')') {
if (s->top != -1 && top(s) == '(') {
pop(s);
} else {
ch = a[i];
flag = 1;
break;
}
} else if (a[i] == ']') {
if (s->top != -1 && top(s) == '[') pop(s);
else {
ch = a[i];
flag = 1;
break;
}
} else if (a[i] == '}') {
if (s->top != -1 && top(s) == '{') pop(s);
else {
ch = a[i];
flag = 1;
break;
}
} else if (a[i] == '>') {
if (s->top != -1 && top(s) == '<') pop(s);
else {
ch = a[i];
flag = 1;
break;
}
}
}

if (!flag && cheekEmpty(s)) {
printf("YES\n");
} else {
printf("NO\n");
if (!cheekEmpty(s)) {
if (top(s) == '<') printf("/*-?\n");
else printf("%c-?\n", top(s));
} else {
if (ch == '>') printf("?-*/\n");
else printf("?-%c\n", ch);
}
}

return 0;
}

/**
* 创建新栈
* @return
*/
Stack creat() {
Stack s = (Stack) malloc(sizeof(struct StackRecord));
s->top = -1;
s->array = (char *) malloc(sizeof(char) * Maxsize);
return s;
}

/**
* 判断是否为空栈
* @param s
* @return
*/
int cheekEmpty(Stack s) {
if (s->top == -1)
return 1;
else
return 0;
}

/**
*添加元素
* @param s
* @param x
*/
void push(Stack s, char x) {
s->array[++(s->top)] = x;
}

/**
*删除
* @param s
*/
void pop(Stack s) {
s->top--;
}

/**
*取出
* @param s
*/
char top(Stack s) {
return s->array[s->top];
}

7-3 银行业务队列简单模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>

const int MAX = 1010;

int main() {

int a[MAX], b[MAX], cnta, cntb;
cnta = cntb = 0;
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int temp;
scanf("%d", &temp);
if (temp % 2) a[++cnta] = temp;
else b[++cntb] = temp;
}
int flag = 0, x = 1, y = 1;
while (x <= cnta || y <= cntb) {
if (x <= cnta) {
if (flag++) printf(" ");
printf("%d", a[x++]);
}
if (x <= cnta) {
if (flag++) printf(" ");
printf("%d", a[x++]);
}
if (y <= cntb) {
if (flag++) printf(" ");
printf("%d", b[y++]);
}
}
return 0;
}

7-4 顺序存储的二叉树的最近的公共祖先问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <stdio.h>

int find(int i, int j);

int main() {
int n, i, j, m;
int a[1000];
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
scanf("%d %d", &i, &j);

if (a[i] == 0)//查错
{
printf("ERROR: T[%d] is NULL\n", i);
return 0;
}
if (a[j] == 0)//查错
{
printf("ERROR: T[%d] is NULL\n", j);
return 0;
}
m = find(i, j);
printf("%d %d", m, a[m]);
return 0;
}

/**
* 查找公共祖先,二分查找
* @param i
* @param j
* @return
*/
int find(int i, int j) {
if (i == j) {
return i;
} else if (i > j) {
return find(i / 2, j);
} else if (i < j) {
return find(i, j / 2);
}
}

7-5 修理牧场

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include<stdio.h>
#include<stdlib.h>

typedef int ElemType;
typedef struct HuffmanTreeNode {
ElemType data; //哈夫曼树中节点的权值
struct HuffmanTreeNode *left;
struct HuffmanTreeNode *right;
} HuffmanTreeNode, *HuffmanTree;

HuffmanTree createHuffmanTree(ElemType arr[], int N) {
HuffmanTree treeArr[N];
HuffmanTree tree, pRoot = NULL;

for (int i = 0; i < N; i++) { //初始化结构体指针数组,数组中每一个元素为一个结构体指针类型
tree = (HuffmanTree) malloc(sizeof(HuffmanTreeNode));
tree->data = arr[i];
tree->left = tree->right = NULL;
treeArr[i] = tree;
}

for (int i = 1; i < N; i++) { //进行 n-1 次循环建立哈夫曼树

//k1为当前数组中第一个非空树的索引,k2为第二个非空树的索引
int k1 = -1, k2 = 0;
for (int j = 0; j < N; j++) {
if (treeArr[j] != NULL && k1 == -1) {
k1 = j;
continue;
}
if (treeArr[j] != NULL) {
k2 = j;
break;
}
}
//循环遍历当前数组,找出最小值索引k1,和次小值索引k2
for (int j = k2; j < N; j++) {
if (treeArr[j] != NULL) {
if (treeArr[j]->data < treeArr[k1]->data) {//最小
k2 = k1;
k1 = j;
} else if (treeArr[j]->data < treeArr[k2]->data) {//次小
k2 = j;
}
}
}
//由最小权值树和次最小权值树建立一棵新树,pRoot指向树根结点
pRoot = (HuffmanTree) malloc(sizeof(HuffmanTreeNode));
pRoot->data = treeArr[k1]->data + treeArr[k2]->data;
pRoot->left = treeArr[k1];
pRoot->right = treeArr[k2];

treeArr[k1] = pRoot; //将新生成的数加入到数组中k1的位置
treeArr[k2] = NULL; //k2位置为空
}

return pRoot;
}

ElemType calculateWeightLength(HuffmanTree ptrTree, int len) {
if (ptrTree == NULL) { //空树返回0
return 0;
} else {
if (ptrTree->left == NULL && ptrTree->right == NULL) { //访问到叶子节点
return ptrTree->data * len;
} else {
return calculateWeightLength(ptrTree->left, len + 1) + calculateWeightLength(ptrTree->right, len + 1); //向下递归计算
}
}
}

int main() {
ElemType arr[10001];
int i = 0, N;
scanf("%d", &N);

while (i < N)
scanf("%d", &arr[i++]);

HuffmanTree pRoot = createHuffmanTree(arr, N); //返回指向哈夫曼树根节点的指针

printf("%d", calculateWeightLength(pRoot, 0));

return 0;
}

7-6 公路村村通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <stdlib.h>

int fa[1005];

typedef struct {
int l;
int r;
int weight;
} Node;

Node p[3005];
int n, m, sum, cnt;

int cmp(const void *a, const void *b) {
Node *p1 = (Node *) a;
Node *p2 = (Node *) b;
return p1->weight - p2->weight;
}

int Find(int x) {
return (x == fa[x]) ? (x) : (fa[x] = Find(fa[x]));
}

void Union(int x, int y) {
fa[Find(x)] = Find(y);
}

int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
fa[i] = i;
for (int i = 0; i < m; i++)
scanf("%d %d %d", &p[i].l, &p[i].r, &p[i].weight);
qsort(p, m, sizeof(Node), cmp);
for (int i = 0; i < m; i++) {
if (Find(p[i].l) != Find(p[i].r)) {
sum += p[i].weight;
Union(p[i].l, p[i].r);
cnt++;
}
if (cnt == n - 1)
break;
}
if (cnt == n - 1)
printf("%d\n", sum);
else
printf("-1\n");
return 0;
}

7-7 畅通工程之最低成本建设问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <stdlib.h>

struct path {
int a, b, c;
} p[3000];
int f[1001], n, m;

void init() {
for (int i = 1; i <= n; i++) f[i] = i;
}

int getf(int k) {
if (f[k] == k) return f[k];
return f[k] = getf(f[k]);
}

int cmp(const void *a, const void *b) {
return ((struct path *) a)->c - ((struct path *) b)->c;
}

int main() {
scanf("%d%d", &n, &m);
init();
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &p[i].a, &p[i].b, &p[i].c);
}
qsort(p, m, sizeof(p[0]), cmp);
int c = 0, ans = 0;
for (int i = 0; i < m; i++) {
if (getf(p[i].a) != getf(p[i].b)) {
ans += p[i].c;
c++;
f[getf(p[i].a)] = getf(p[i].b);
}
}
if (c < n - 1) printf("Impossible\n");
else printf("%d\n", ans);
return 0;
}

7-8 最短工期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int n, m, ans;
int mp[100][100];
int l[100], q[100], t[100];

int main() {
int a, b, c, head = 0, tail = 0;
scanf("%d%d", &n, &m);
memset(mp, -1, sizeof(mp));
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &a, &b, &c);
mp[a][b] = c;
l[b]++;
}
for (int i = 0; i < n; i++) {
if (!l[i]) {
q[tail++] = i;
}
}
while (head < tail) {
int temp = q[head++];
if (t[temp] > ans) ans = t[temp];
for (int i = 0; i < n; i++) {
if (mp[temp][i] != -1) {
l[i]--;
if (!l[i]) q[tail++] = i;
if (t[i] < t[temp] + mp[temp][i]) {
t[i] = t[temp] + mp[temp][i];
}
}
}
}
if (tail < n) printf("Impossible");
else printf("%d", ans);
}

7-9 哈利·波特的考试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* 7-9 哈利·波特的考试
* 最短路径 迪杰斯特拉算法
*/
#include<stdio.h>
#include<string.h>

#define maxInt 2147483647

typedef struct {
int arcs[102][102];
int vexnum, arcnum;
} MGraph;

int final[102];//final[w]=1表示求得顶点v0至vw的最短路径
int D[102]; //记录v0到vi的当前最短路径长度
int P[102]; //记录v0到vi的当前最短路径vi的前驱

int i, u, j, m, v, min, w, k, a, b, c, min1 = 999999, max = -991111, p = 0;

void Dijkstra(MGraph G, int v0) {
for (v = 0; v < G.vexnum; v++) //初始化数据
{
final[v] = 0; //全部顶点初始化为未知最短路径状态
D[v] = G.arcs[v0][v];// 将与v0点有连线的顶点加上权值
P[v] = -1; //初始化路径数组P为-1
}

D[v0] = 0; //v0至v0路径为0
final[v0] = 1; // v0至v0不需要求路径
// 开始主循环,每次求得v0到某个v顶点的最短路径
for (v = 1; v < G.vexnum; v++) {
min = maxInt; // 当前所知离v0顶点的最近距离
for (w = 0; w < G.vexnum; w++) // 寻找离v0最近的顶点
{
if (!final[w] && D[w] < min) {
k = w;
min = D[w]; // w顶点离v0顶点更近
}
}
final[k] = 1; // 将目前找到的最近的顶点置为1
for (w = 0; w < G.vexnum; w++) // 修正当前最短路径及距离
{
// 如果经过v顶点的路径比现在这条路径的长度短的话
if (!final[w] && (min + G.arcs[k][w] < D[w])) { // 说明找到了更短的路径,修改D[w]和P[w]
D[w] = min + G.arcs[k][w]; // 修改当前路径长度
P[w] = k;
}
}
}
}

int main() {
MGraph G;
memset(final, 0, sizeof(final));
memset(D, 0x3f3f3f3f, sizeof(D));
memset(G.arcs, 0x3f3f3f3f, sizeof(G.arcs)); //邻接矩阵一定要初始化
scanf("%d %d", &G.vexnum, &m);
for (i = 0; i < m; i++) {
scanf("%d %d %d", &a, &b, &c);
G.arcs[a - 1][b - 1] = c;
G.arcs[b - 1][a - 1] = c;
}
for (u = 0; u < G.vexnum; u++) {
max = -9999999;
Dijkstra(G, u);
for (j = 0; j < G.vexnum; j++) {
if (D[j] > max)
max = D[j];
}
if (max < min1) {
min1 = max;
p = u + 1;
}

}
if (p == 0)
printf("0");
else
printf("%d %d\n", p, min1);
return 0;
}

7-10 旅游规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* 7-10 旅游规划
* 最短路径 弗洛伊德算法
*/

#include<stdio.h>

#define MAXN 500
#define ERROR -1
#define Infinite 65534

int N, M, S, D;//城市的个数 高速公路的条数 出发地 目的地
int Dist[MAXN][MAXN], Cost[MAXN][MAXN];//距离与花费矩阵
int dist[MAXN], cost[MAXN], visit[MAXN];//最短距离与花费 标记数组

void Inicialization(void);

void FindTheWay(void);

int FindMinWay(void);

int main() {
scanf("%d %d %d %d", &N, &M, &S, &D);//城市的个数 高速公路的条数 出发地 目的地
Inicialization();//初始化
FindTheWay();
printf("%d %d", dist[D], cost[D]);
return 0;
}

void Inicialization(void) {
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
Dist[i][j] = Cost[i][j] = Infinite;//矩阵初始化为无限值

int v1, v2, d, c;
for (int i = 0; i < M; i++) {
scanf("%d %d %d %d", &v1, &v2, &d, &c);
Dist[v1][v2] = Dist[v2][v1] = d;//输入距离路径
Cost[v1][v2] = Cost[v2][v1] = c;//输入花费路径
}

for (int i = 0; i < N; i++)
dist[i] = cost[i] = Infinite;//矩阵初始化为无限值
}

void FindTheWay(void) {
dist[S] = cost[S] = 0;//出发地为0
visit[S] = 1;//出发地访问标记
int v;
for (int i = 0; i < N; i++)//记录出发地直达的路径
if (!visit[i] && Dist[S][i] < Infinite) //如果没访问 且有路径
{
dist[i] = Dist[S][i];
cost[i] = Cost[S][i];
}
while (1) {
v = FindMinWay();//找出最短出发地直达且未访问的城市
if (v == ERROR) break;
visit[v] = 1;//找出城市的访问标记

for (int i = 0; i < N; i++)//循环每个城市
if (!visit[i] && Dist[v][i] < Infinite)//如果未访问且有路径
if ((dist[v] + Dist[v][i] < dist[i]) ||
(dist[v] + Dist[v][i] == dist[i] && cost[v] + Cost[v][i] < cost[i])) {//如果从先到该城市再到另一城市距离小于直接到另一城市
//或者从先到该城市再到另一城市距离等于直接到另一城市,且花费少
dist[i] = dist[v] + Dist[v][i];//更新最短路径
cost[i] = cost[v] + Cost[v][i];
}
}
}

int FindMinWay(void) {
int min = Infinite;
int temp;

for (int i = 0; i < N; i++)//循环每个城市 找出最短的路径
if (!visit[i] && dist[i] < min) {
min = dist[i];
temp = i;
}
if (min == Infinite) return ERROR;
return temp;
}

7-11 QQ帐户的申请与登陆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/**
* 7-11 QQ帐户的申请与登陆
* 哈希表 分离链接法
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/*账号与密码最大长度的定义
它们的最大长度需要比题目所给的大一位
这是因为还需要一个位置来储存'\0'来判断字符串的结尾*/
#define Max_Password_Len 17
#define Max_Account_Len 11
#define MaxTableSize 1000000

/*各种状态的定义
最好用正数表示成功的状态
用负数或0表示失败的状态
这样会让强迫症看了舒服一点*/
#define ERROR_WrongPW -2
#define ERROR_Exist -1
#define ERROR_NOTExist 0
#define New_OK 1
#define Login_OK 2

typedef char AccountType[Max_Account_Len];//账号类型定义
typedef char PasswordType[Max_Password_Len];//密码类型定义
typedef int Index;
typedef enum {
New, Log
} Pattern;//两种模式,新建账号与登入账号

typedef struct {
AccountType Account;
PasswordType Password;
} ElemType;//数据类型的定义,每个对应一个用户,内含用户的账号和密码

//链表指针的定义
typedef struct LNode *PtrToLNode;
//链表结点的定义
typedef struct LNode {
PtrToLNode Next;
ElemType Data;
} LNode;
typedef PtrToLNode List;//链表的定义
typedef PtrToLNode Position;//哈希表中结点位置的定义

//哈希表的定义
typedef struct TblNode *HashTable;
typedef struct TblNode {
int TableSize;//哈希表的大小
List Heads;//储存各个列表头节点的数组
} TblNode;

int NextPrime(int N)//返回N的下一个素数
{
int i, P;
P = N % 2 ? N + 2 : N + 1;
//P为N之后的第一个奇数
while (P < MaxTableSize) {
for (i = (int) sqrt(P); i > 2; i--)//因为只考虑奇数,所以i为2时就结束了
if (P % i == 0)
break;
if (i == 2)
break;//i为2说明P为素数
else
P += 2;//i!=2说明P不是素数,则P指向下一个奇数
}
return P;
}

int Hash(int Key, int TableSize) {//返回Key值相对应的哈希值,即其在哈希表中的储存下标
return Key % TableSize;
}

HashTable CreateTable(int TableSize) { //构造空的哈希表
HashTable H;
int i;
H = (HashTable) malloc(sizeof(TblNode));
H->TableSize = NextPrime(TableSize);
H->Heads = (List) malloc(sizeof(LNode) * H->TableSize);
for (i = 0; i < H->TableSize; i++) {
H->Heads[i].Data.Account[0] = '\0';
H->Heads[i].Data.Password[0] = '\0';
H->Heads[i].Next = NULL;
}
return H;
}

Position Find(HashTable H, ElemType Key) {
Position Pos;
Index p;
if (strlen(Key.Account) > 5) //账号大于5位时取最后5位
p = Hash(atoi(Key.Account +
strlen(Key.Account) - 5), H->TableSize);
else//账号不大于5位则等于它本身
p = Hash(atoi(Key.Account), H->TableSize);
Pos = H->Heads[p].Next;
while (Pos && strcmp(Key.Account, Pos->Data.Account))
Pos = Pos->Next;
return Pos;//Pos指向用户数据的位置,没有注册就返回NULL
}

int NewOrLog(HashTable H, ElemType Key, Pattern P) { //返回状态参数
Position Pos, NewPos;
Index p;
Pos = Find(H, Key);
switch (P) {
case Log:
if (Pos == NULL)
return ERROR_NOTExist;//登陆时不存在账号
else if (strcmp(Pos->Data.Password, Key.Password) ||
(strlen(Key.Password) > 16 || strlen(Key.Password) < 6))
return ERROR_WrongPW; //密码错误或格式错误
else
return Login_OK;//账号和密码均正确,可以登录
case New:
if (Pos != NULL)
return ERROR_Exist; //新建账号时发现已经存在这样的账号了
else {
NewPos = (Position) malloc(sizeof(LNode));
strcpy(NewPos->Data.Account, Key.Account);
strcpy(NewPos->Data.Password, Key.Password);
if (strlen(Key.Account) > 5)
p = Hash(atoi(Key.Account +
strlen(Key.Account) - 5), H->TableSize);
else
p = Hash(atoi(Key.Account), H->TableSize);
NewPos->Next = H->Heads[p].Next;
H->Heads[p].Next = NewPos;
return New_OK; //插入新值并返回插入成功
}
}
}

void DestroyTable(HashTable H) { //销毁哈希表
PtrToLNode p, q;
int i;
for (i = 0; i < H->TableSize; i++) {
q = H->Heads[i].Next;
while (q) {
p = q->Next;
free(q);
q = p;
}
}
free(H);
}

int main(void) {
int N, i;
ElemType Key;
char Input;
Pattern P;
HashTable H;
scanf("%d", &N);
H = CreateTable(2 * N);
for (i = 0; i < N; i++) {
scanf("\n%c %s %s", &Input, Key.Account, Key.Password);
P = (Input == 'L') ? Log : New;
switch (NewOrLog(H, Key, P)) {//最后根据不同返回值输出对应状态即可
case ERROR_Exist:
printf("ERROR: Exist\n");
break;
case ERROR_NOTExist:
printf("ERROR: Not Exist\n");
break;
case ERROR_WrongPW:
printf("ERROR: Wrong PW\n");
break;
case Login_OK:
printf("Login: OK\n");
break;
case New_OK:
printf("New: OK\n");
break;
}
}
DestroyTable(H);
return 0;
}

7-12 人以群分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* 7-12 人以群分
* 排序
*/

#include <stdio.h>
#include <stdlib.h>

int comfunc(const void *elem1, const void *elem2);

void sort_character(int *p, int n);

int main() {
int n, i;
int a[100001];

scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
qsort(a, n, sizeof(int), comfunc);
sort_character(a, n);

return 0;
}

int comfunc(const void *elem1, const void *elem2) {
int *p1 = (int *) elem1;
int *p2 = (int *) elem2;

return *p1 - *p2;
}

void sort_character(int *p, int n) {
int i, j, n1, n2, sum1, sum2, dif, dif1, dif2;

sum1 = sum2 = 0;
dif = dif1 = dif2 = 0;
if (n % 2 == 0) {
n1 = n2 = n / 2;
for (i = 0; i < n1; i++)
sum1 += p[i];
for (i = n1; i < n; i++)
sum2 += p[i];
dif = abs(sum2 - sum1);
} else {
n1 = n2 = n / 2;
for (i = 0; i < n1; i++)
sum1 += p[i];
for (i = n / 2 + 1; i < n; i++)
sum2 += p[i];
dif1 = abs(sum1 + p[n1] - sum2);
dif2 = abs(sum2 + p[n2] - sum1);
dif = (dif1 > dif2) ? dif1 : dif2;
if (dif1 > dif2)
n1++;
else
n2++;
}
printf("Outgoing #: %d\n", n2);
printf("Introverted #: %d\n", n1);
printf("Diff = %d\n", dif);

}

7-13 寻找大富翁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 7-13 寻找大富翁
* 堆排序和选择排序
*/

#include <stdio.h> //堆排序; 注意:此算法中,下标从1开始

#define max 1000010
int num[max];

void sift(int *num, int low, int high) //将下标为low位置上的点调到适当位置
{
int i, j, temp;
i = low;
j = 2 * i; //num[j]是num[i]的左孩子结点;
temp = num[i]; //待调整的结点
while (j <= high) {
if (j < high && num[j] < num[j + 1]) //如果右孩子比较大,则把j指向右孩子,j变为2*i+1;
++j;
if (temp < num[j]) {
num[i] = num[j]; //将num[j]调整到双亲结点的位置上;
i = j; //修改i和j的值,以便继续向下调整;
j = i * 2;
} else break; //调整结束;
}
num[i] = temp; //被调整的结点放入最终位置
}

int main() {
int n, m, i, temp, count = 0;
scanf("%d%d", &n, &m);
for (i = 1; i <= n; i++)
scanf("%d", &num[i]);
if (n < m) m = n; //注意,有一个测试点是n小于m的情况,这时,只用排前n个;
for (i = n / 2; i >= 1; i--) //所有结点建立初始堆
sift(num, i, n);
for (i = n; i >= 2; i--) //进行n-1次循环,完成堆排序
{
/*以下3句换出了根节点中的关键字,将其放入最终位置*/
temp = num[1];
num[1] = num[i];
num[i] = temp;
count++;
if (count == 1)
printf("%d", num[i]);
else
printf(" %d", num[i]);
if (count == m) break; //打印前m个;
sift(num, 1, i - 1); //减少了1个关键字的无序序列,继续调整。
}
if (m == n) printf(" %d", num[1]); //当n<m的特殊情况下,上面只打印了n~2,还有最后一个下标为1的没有打印,故再打印一个。
return 0;
}

7-14 PAT排名汇总

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
* 7-14 PAT排名汇总
* 快速排序
*/
#include <stdio.h>
#include <string.h>

struct stu {
char id[14]; //考号
int score; //分数
int kc; //考场
};
struct stu a[30000];

int bigger(const char *s1, const char *s2) {
for (int i = 0; i < 13; i++)
if (s1[i] > s2[i])
return 1;
else if (s1[i] < s2[i])
return 0;
return 1;
}

void qsort(int l, int r) {
if (l >= r)
return;

int i = l;
int j = r;

struct stu t = a[l];
while (i != j) {
while (i < j && (a[j].score < t.score || a[j].score == t.score && bigger(a[j].id, t.id)))
j--;
while (i < j && (a[i].score > t.score || a[i].score == t.score && bigger(t.id, a[i].id)))
i++;
if (i < j) {
struct stu s = a[i];
a[i] = a[j];
a[j] = s;
}
}
a[l] = a[i];
a[i] = t;

qsort(l, i - 1);
qsort(i + 1, r);

return;
}

void Copy(int *b2, int *b1, int n) {
for (int i = 1; i <= n; i++)
b2[i] = b1[i];
}

int main() {
int n, j, i, top = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
int k;
scanf("%d", &k);
for (j = 0; j < k; j++) {
char id[14];
int score;
scanf("%s %d", id, &score);
a[top].score = score;
a[top].kc = i;
strcpy(a[top].id, id);
top++;
}
}
qsort(0, top - 1);

int levall = 1, b1[n + 1], b2[n + 1], score = a[0].score;

for (i = 1; i <= n; i++)
b1[i] = 1, b2[i] = 1;
printf("%d\n", top);
printf("%s %d %d %d\n", a[0].id, 1, a[0].kc, 1);
int llevall = 1; //上一个总排名
levall = 2; //总排名

Copy(b2, b1, n);
b1[a[0].kc]++;
for (i = 1; i < top; i++) {
if (a[i].score == a[i - 1].score) {
printf("%s %d %d %d\n", a[i].id, llevall, a[i].kc, b2[a[i].kc]);
levall++;
b1[a[i].kc]++;
} else {
printf("%s %d %d %d\n", a[i].id, levall, a[i].kc, b1[a[i].kc]);
llevall = levall;
levall++;

Copy(b2, b1, n);
b1[a[i].kc]++; //考场的排名
}
}
return 0;
}