0%

软件技术基础第三次实验

先放工程文件内容

第一个实验代码

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
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#pragma warning(disable:4996)
typedef struct student//结构体本体
{
int elem;
char num;
struct student *next;
}link;
link * creatLink(int * initelem, int len) //头插法初始化链表
{
int i;
//最初状态下,头指针 H 没有任何结点,所以,插入第一个元素,就相当于是创建结点 H
link *H = (link*)malloc(sizeof(link));
H->elem = initelem[0];
H->next = NULL;
//如果采用头插法插入超过 1 个元素,则可添加到第一个结点 H 之前
for (i = 2; i < len*2; i++)
{
link * a = (link*)malloc(sizeof(link));
a->elem = initelem[i];
//插入元素时,首先将插入位置后的链表链接到新结点上
scanf_s("%c", &(a->num));
a->next = H;
//然后再链接头指针 H
H = a;
}
return H;
}
void display(struct student *p) //打印函数
{
while (((p->elem) > 1) && ((p->elem) = 1)) {
printf("%c", p->num);
p = p->next;
}
printf("\n");
}
int Length(struct student * L)//表长统计函数
{
int len = 0; //统计表长
struct student *p = L;
while (p->next != NULL) {
p = p->next;
len = len + 1;
}
return len/2;
}
int main(void)
{
int a, i;
int elem[20] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 };
printf(" 栈长度:");
scanf("%d", &i);
link *Head = creatLink(elem, i + 1);//建立动态存储链表
printf("\n结构体总长度:%d\n", Length(Head));//调用长度统计函数
if (Head->next == NULL)
printf("空\n");
else
printf("非空\n");//判断单链表是否为空
display(Head);//调用输出函数
free(Head);//释放栈
system("pause");
return 0;
}

第二个实验代码

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
// 队列(链队列)还有,这不是我的原创代码,但我稍微改了改,并补充了注释。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#pragma warning(disable:4996)

#define OK 1 // 执行成功
#define ERROR 0 // 执行失败
#define TRUE 1 // 返回值为真
#define FALSE 0 // 返回值为假

typedef int Status; // 函数返回结果类型


typedef struct QNode // 队列节点
{
char data; // 元素值
struct QNode *next; // 指向下一个节点的指针
} QNode, *QueuePtr;

typedef struct // 链队列结构
{
QueuePtr front, rear; // 队头指针、队尾指针
} LinkQueue;

Status InitQueue(LinkQueue *Q) // 初始化队列
{
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));// 为队头和队尾指针分配内存
if (!Q->front || !Q->rear) // 内存分配失败,结束程序
{
exit(OVERFLOW);
}
Q->front->next = NULL; // 队头节点指向NULL
return OK;
}

Status DestroyQueue(LinkQueue *Q) // 销毁队列
{

while (Q->front) // 当队列中还有元素的情况
{
Q->rear = Q->front->next;// 队尾指针指向队头指针的下一个元素
free(Q->front); // 释放队头指针所在节点
Q->front = Q->rear; // 队头指针指向队尾指针(即原来的下一个元素)
}
return OK;
}

Status ClearQueue(LinkQueue *Q) // 清空队列
{
QueuePtr p, q; // p用来遍历队列节点,q用来指向被删除的节点

Q->rear = Q->front; // 队尾指针指向队头指针
p = Q->front->next; // p指向队头指针的下一个节点
Q->front->next = NULL; // 队头指针的下一个节点指向NULL(表示删除之后的所有元素)
while (p) // 当队列中还有元素,释放头节点之后的所有节点
{
q = p; // q节点指向被删除节点
p = p->next; // p指向队列的下一个节点
free(q); // 释放q节点
}
return OK;
}

Status QueueEmpty(LinkQueue Q)// 判断队列是否为空
{
if (Q.front == Q.rear) // 头指针和尾指针位置相等,队列为空
{
return TRUE;
}
else
{
return FALSE;
}
}

int QueueLength(LinkQueue Q) // 统计队列长度
{
int i = 0; // 用于统计队列长度的计数器
QueuePtr p; // 用于遍历队列的元素
p = Q.front; // p指向队头节点
while (p != Q.rear) // 当p没有移动到队尾指针位置
{
i++; // 计数器加1
p = p->next; // p移动到队列的下一个节点
}
return i/2; // 返回队列长度
}

Status GetHead(LinkQueue Q, char *e) // 获取队列头元素
{
QueuePtr p;
if (Q.front == Q.rear) // 队列为空,获取失败
{
return ERROR;
}
p = Q.front->next; // p指向队列的第一个元素
*e = p->data; // 将队列头元素的值赋值给e元素
return OK;
}

Status EnQueue(LinkQueue *Q, char e) // 在队列的队尾处插入元素
{
QueuePtr s = (QueuePtr)malloc(sizeof(QNode));// 给新节点分配空间
if (!s) // 分配空间失败,结束程序
{
exit(OVERFLOW);
}
s->data = e; // 将值赋值给新节点
s->next = NULL; // 新节点指向NULL
Q->rear->next = s; // 队尾指针的下一个元素指向新节点
Q->rear = s; // 队尾指针指向新节点(新节点成为队尾指针的指向的节点)
return OK;
}

Status DeQueue(LinkQueue *Q, char *e) // 删除队头元素
{
QueuePtr p; // 用于指向被删除节点
if (Q->front == Q->rear) // 队列为空,出队失败
{
return ERROR;
}
p = Q->front->next; // p指向队列的第一个元素
*e = p->data; // 将队列头节点的值赋值给元素e
Q->front->next = p->next; // 头指针的下一个节点指向下下个节点(跳过头节点)
if (Q->rear == p) // 如果被删除节点是队尾指针指向的节点(删除后队列为空)
{
Q->rear = Q->front; // 队尾指针指向队头指针
}
free(p); // 释放队头节点
return OK;
}

Status visit(char e) // 打印单个元素
{
printf("%s",&e);
return OK;
}

Status QueueTravel(LinkQueue Q) // 遍历队列中的元素
{
QueuePtr p; // 用于遍历队列中的节点
p = Q.front->next; // p指向头节点
printf("[ ");
while (p) // 当队列中还有元素
{
visit(p->data); // 打印当前节点的值
p = p->next; // p移动到队列下一个位置
}
printf("]\n");
return OK;
}
/**写在主函数前的注释**/
/**所有的函数返回值均为执行状态确定函数是否执行成功**/
int main()
{
Status status; // 定义执行状态(所有的函数返回值均为这个数据结构)的结构类型
int j,len; // j用来遍历,len用于设定链队长度
char i; //i用来传递字符信息
char e; //e用来临时储存输出字符信息
LinkQueue Q; // 队列
InitQueue(&Q); // 初始化队列
printf("初始化队列后,队列是否为空?%s\n", QueueEmpty(Q) == TRUE ? "是" : "否");//确认初始化后队列为空
/***开始向队列插入元素,并打印队列***/
printf("请输入生成队列长度:"); scanf("%d", &len);
printf("\n请输入队列元素\n");
for (j = 1; j <= len*2; ++j) //向队列中插入len个元素
{
scanf("%c",&i);
EnQueue(&Q, i); // 调用EnQueue函数依次将元素i插入队列
}
printf("插入%d个元素后队列的值为:",len);//输出队列
QueueTravel(Q); // 遍历队列
printf("队列的长度为:%d\n", QueueLength(Q)); // 获取队列长度并输出
/*** 删除队列中的全部元素,并打印对应的值 ***/
printf("开始删除元素:\n");
for (j = 0; j < len*2; ++j) //在队列中出队len个元素
{
DeQueue(&Q, &e); // 删除队头元素,将值存到e中
printf("元素%s出队\n", &e);
}
printf("%d个元素出队后,队列中的值为:",len);//全部出队后再输出
QueueTravel(Q); // 遍历队列
printf("队列的长度为:%d\n", QueueLength(Q)); // 获取队列长度
/*** 清空队列元素,并释放头指针 ***/
ClearQueue(&Q); // 清空队列元素
printf("清空队列后,队列是否为空:%s\n", QueueEmpty(Q) == TRUE ? "是" : "否");
printf("队列中的元素为:");
QueueTravel(Q); // 遍历元素
return 0;
}
/**唯一的BUG就是会在出队的时候输出锟斤拷,但依旧可以看到依次输出的a,b,c,d**/
欢迎打赏