♻️ 更新测试数据的录入方式

This commit is contained in:
康建伟
2019-11-07 12:16:00 +08:00
parent 8698741ed5
commit d3a731b617
41 changed files with 1399 additions and 716 deletions

View File

@@ -149,8 +149,8 @@ int main(int argc, char** argv) {
printf("████████ CreateList_Head \n");
{
LinkList L;
CreateList_Head(&L, 5, "TestData_Head.txt");
printf("█ 头插法建立单链表 L = ");
CreateList_Head("TestData_Head.txt", &L, 5);
ListTraverse(L, PrintElem);
}
PressEnterToContinue();
@@ -159,8 +159,8 @@ int main(int argc, char** argv) {
printf("████████ CreateList_Tail \n");
{
LinkList L;
CreateList_Tail(&L, 5, "TestData_Tail.txt");
printf("█ 尾插法建立单链表 L = ");
CreateList_Tail("TestData_Tail.txt", &L, 5);
ListTraverse(L, PrintElem);
}
PressEnterToContinue();

View File

@@ -384,105 +384,149 @@ void ListTraverse(LinkList L, void(Visit)(ElemType)) {
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Head(LinkList* L, int n, ...) {
int i;
LinkList p;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L == NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个降序元素", n);
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p == NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
} else {
fclose(fp);
}
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
}
fclose(fp);
}
fclose(fp);
return OK;
}
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Tail(LinkList* L, int n, ...) {
int i;
LinkList p, q;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L==NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个升序元素", n);
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p==NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
q->next = p;
q = q->next;
} else {
fclose(fp);
}
q->next = NULL;
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
q->next = p;
q = q->next;
}
q->next = NULL;
fclose(fp);
}
q->next = NULL;
fclose(fp);
return OK;
}

View File

@@ -8,7 +8,9 @@
#define LINKLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供 malloc、realloc、free、exit 原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
/* 单链表元素类型定义 */
@@ -147,22 +149,31 @@ void ListTraverse(LinkList L, void(Visit)(ElemType));
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n);
Status CreateList_Head(LinkList* L, int n, ...);
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n);
Status CreateList_Tail(LinkList* L, int n, ...);
#endif

View File

@@ -34,105 +34,149 @@ void ListTraverse(LinkList L, void(Visit)(ElemType)) {
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Head(LinkList* L, int n, ...) {
int i;
LinkList p;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L == NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个降序元素", n);
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p == NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
} else {
fclose(fp);
}
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
}
fclose(fp);
}
fclose(fp);
return OK;
}
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Tail(LinkList* L, int n, ...) {
int i;
LinkList p, q;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L==NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个升序元素", n);
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p==NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
q->next = p;
q = q->next;
} else {
fclose(fp);
}
q->next = NULL;
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
q->next = p;
q = q->next;
}
q->next = NULL;
fclose(fp);
}
q->next = NULL;
fclose(fp);
return OK;
}

View File

@@ -8,7 +8,9 @@
#define LINKLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
/* 单链表元素类型定义 */
@@ -40,22 +42,31 @@ void ListTraverse(LinkList L, void(Visit)(ElemType));
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n);
Status CreateList_Head(LinkList* L, int n, ...);
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n);
Status CreateList_Tail(LinkList* L, int n, ...);
#endif

View File

@@ -10,15 +10,15 @@ void PrintElem(ElemType e) {
int main(int argc, char** argv) {
LinkList La, Lb, Lc;
int m = 5;
int n = 5;
printf("作为示例La长度设定为 %d Lb长度设定为 %d 创建La和Lb...\n", m, m);
printf("作为示例La长度设定为 %d Lb长度设定为 %d 创建La和Lb...\n", n, n);
CreateList_Head("TestData_Head.txt", &La, m);
CreateList_Head(&La, n, "TestData_Head.txt");
printf("La = ");
ListTraverse(La, PrintElem);
CreateList_Tail("TestData_Tail.txt", &Lb, m);
CreateList_Tail(&Lb, n, "TestData_Tail.txt");
printf("Lb = ");
ListTraverse(Lb, PrintElem);

View File

@@ -11,8 +11,10 @@ int main(int argc, char** argv) {
SLinkList space; // 备用空间
int S; // 静态链表
// S = (A-B)(B-A)
difference(space, &S, "TestData.txt");
printf("S = (A-B)(B-A) = ");
difference("TestData.txt", space, &S);
ListTraverse(space, S, PrintElem);
return 0;

View File

@@ -13,18 +13,33 @@
*
* 对集合A和集合B进行(A-B)(B-A)计算计算结果存入静态链表S
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void difference(char path[], SLinkList space, int* S) {
FILE* fp;
void difference(SLinkList space, int* S, ...) {
int m, n; // 集合A和集合B中元素数量
int j; // 循环计数器
int R; // 指向静态链表最后一个结点
int i, k, p;
int b; // 临时存储从集合B中读到的数据
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, S);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
// 初始化备用空间
InitSpace(space);
@@ -35,14 +50,25 @@ void difference(char path[], SLinkList space, int* S) {
// 让R执行静态链表最后的结点
R = *S;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
// 读取集合A和集合B的元素个数
if(readFromConsole) {
printf("请输入集合A的元素个数");
scanf("%d", &m);
printf("请输入集合B的元素个数");
scanf("%d", &n);
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
ReadData(fp, "%d%d", &m, &n);
}
// 读取集合A和集合B的元素个数
ReadData(fp, "%d%d", &m, &n);
if(readFromConsole) {
printf("请输入 %d 个元素存入集合A", m);
}
// 录入集合A的数据
for(j = 1; j <= m; ++j) {
@@ -50,7 +76,11 @@ void difference(char path[], SLinkList space, int* S) {
i = Malloc(space);
// 输入集合A的元素值
ReadData(fp, "%d", &space[i].data);
if(readFromConsole) {
scanf("%d", &space[i].data);
} else {
ReadData(fp, "%d", &space[i].data);
}
// 将新结点插入到表尾
space[R].cur = i;
@@ -60,10 +90,18 @@ void difference(char path[], SLinkList space, int* S) {
// 尾结点的指针置空
space[R].cur = 0;
if(readFromConsole) {
printf("请输入 %d 个元素存入集合B", n);
}
// 录入集合B的数据
for(j = 1; j <= n; ++j) {
// 输入集合B的元素值
ReadData(fp, "%d", &b);
if(readFromConsole) {
scanf("%d", &b);
} else {
ReadData(fp, "%d", &b);
}
p = *S; // 指向静态链表头结点后续总是指向k的前一个位置
k = space[*S].cur; // 指向静态链表中的首个元素
@@ -91,5 +129,7 @@ void difference(char path[], SLinkList space, int* S) {
}
}
fclose(fp);
}
if(!readFromConsole) {
fclose(fp);
}
}

View File

@@ -8,8 +8,10 @@
#define DIFFERENCE_H
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SLinkList.h" //**▲02 线性表**//
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
#include "SLinkList.h" //**▲02 线性表**//
/*
* ████████ 算法2.17 ████████
@@ -18,11 +20,16 @@
*
* 对集合A和集合B进行(A-B)(B-A)计算计算结果存入静态链表S
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void difference(char path[], SLinkList space, int* S);
void difference(SLinkList space, int* S, ...);
#endif

View File

@@ -1,5 +1,7 @@
#include <stdio.h>
#include "MergeEList.h" //**▲02 线性表**//
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "MergeEList.h" //**▲02 线性表**//
// 测试函数,打印元素
void PrintElem(ElemType e) {
@@ -21,32 +23,61 @@ int Cmp(ElemType e1, ElemType e2) {
/*
* 尾插法创建链表
*
*
*【备注】
*
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件fp中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreateList_Tail(char path[], ELinkList* L) {
FILE* fp;
void CreateList_Tail(ELinkList* L, ...) {
int i, n;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
fp = fopen(path, "r");
if(fp == NULL) {
printf("文件打开失败...\n");
exit(ERROR);
va_start(ap, L);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 读取指定集合中元素的数量
printf("请输入元素数量:");
scanf("%d", &n);
InitList(L);
printf("请输入 %d 个元素:", n);
for(i = 1; i <= n; i++) {
scanf("%d", &e);
ListInsert(L, i, e);
}
} else {
fp = fopen(path, "r");
if(fp == NULL) {
printf("文件打开失败...\n");
exit(ERROR);
}
// 读取指定集合中元素的数量
ReadData(fp, "%d", &n);
InitList(L);
for(i = 1; i <= n; i++) {
ReadData(fp, "%d", &e);
ListInsert(L, i, e);
}
fclose(fp);
}
// 读取指定集合中元素的数量
ReadData(fp, "%d", &n);
InitList(L);
for(i = 1; i <= n; i++) {
ReadData(fp, "%d", &e);
ListInsert(L, i, e);
}
fclose(fp);
}
@@ -55,11 +86,11 @@ int main(int argc, char** argv) {
printf("创建La和Lb以待测试...\n");
CreateList_Tail("TestData_La.txt", &La);
CreateList_Tail(&La, "TestData_La.txt");
printf("La= ");
ListTraverse(La, PrintElem);
CreateList_Tail("TestData_Lb.txt", &Lb);
CreateList_Tail(&Lb, "TestData_Lb.txt");
printf("Lb= ");
ListTraverse(Lb, PrintElem);

View File

@@ -10,10 +10,10 @@ int main(int argc, char **argv) {
printf("████████ CreatPolyn \n");
{
printf("█ 作为示范,创建项数为 %d 的多项式Pa...\n", m);
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
printf("█ 作为示范,创建项数为 %d 的多项式Pb...\n", n);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pb, n, "TestData_Pb.txt");
}
PressEnterToContinue();
@@ -38,8 +38,8 @@ int main(int argc, char **argv) {
printf("████████ AddPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
AddPolyn(&Pa, &Pb);
@@ -51,8 +51,8 @@ int main(int argc, char **argv) {
printf("████████ SubtractPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
SubtractPolyn(&Pa, &Pb);
@@ -64,8 +64,8 @@ int main(int argc, char **argv) {
printf("████████ MultiplyPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
MultiplyPolyn(&Pa, &Pb);
@@ -76,4 +76,3 @@ int main(int argc, char **argv) {
return 0;
}

View File

@@ -16,17 +16,32 @@
*
* 根据输入的系数和指数创建项数为m的一元多项式
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreatPolyn(char path[], Polynomial* P, int m) {
FILE* fp;
void CreatPolyn(Polynomial* P, int m, ...) {
int i;
ElemType e;
Position h, q;
Link s;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, m);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
// 初始化一个线性链表存放一元多项式
InitList(P);
@@ -39,16 +54,27 @@ void CreatPolyn(char path[], Polynomial* P, int m) {
e.expn = -1;
SetCurElem(h, e);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
if(!readFromConsole) {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
}
if(readFromConsole) {
printf("请输入 %d 个元素:\n", m);
}
// 依次录入m个有效项
for(i = 1; i <= m; i++) {
// 读取系数和指数信息临时存入e
ReadData(fp, "%f%d", &(e.coef), &(e.expn));
if(readFromConsole) {
printf("请输入第 %d 组系数和指数:", i);
scanf("%f%d", &(e.coef), &(e.expn));
} else {
ReadData(fp, "%f%d", &(e.coef), &(e.expn));
}
// 如果当前链表中不存在该指数项
if(LocateElem(*P, e, &q, Cmp) == FALSE && q != NULL) {
@@ -60,7 +86,9 @@ void CreatPolyn(char path[], Polynomial* P, int m) {
}
}
fclose(fp);
if(!readFromConsole) {
fclose(fp);
}
}
/*
@@ -116,9 +144,9 @@ void AddPolyn(Polynomial* Pa, Polynomial* Pb) {
ha = qa;
qa = NextPos(*Pa, qa);
}
break;
break;
// 两者数值相等
// 两者数值相等
case 0: {
sum = a.coef + b.coef;
@@ -146,9 +174,9 @@ void AddPolyn(Polynomial* Pa, Polynomial* Pb) {
qa = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
break;
// 多项式Pb中当前结点的指数值较小
// 多项式Pb中当前结点的指数值较小
case 1: {
// 摘下Pb当前结点
DelFirst(Pb, hb, &qb);
@@ -159,7 +187,7 @@ void AddPolyn(Polynomial* Pa, Polynomial* Pb) {
ha = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
break;
}//switch
}//while
@@ -212,7 +240,7 @@ void SubtractPolyn(Polynomial* Pa, Polynomial* Pb) {
}
break;
// 两者数值相等
// 两者数值相等
case 0: {
sum = a.coef - b.coef;
@@ -240,9 +268,9 @@ void SubtractPolyn(Polynomial* Pa, Polynomial* Pb) {
qa = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
break;
// 多项式Pb中当前结点的指数值较小
// 多项式Pb中当前结点的指数值较小
case 1: {
// 摘下Pb当前结点
DelFirst(Pb, hb, &qb);
@@ -256,7 +284,7 @@ void SubtractPolyn(Polynomial* Pa, Polynomial* Pb) {
ha = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
break;
}//switch
}//while

View File

@@ -8,7 +8,9 @@
#define POLYNOMIAL_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "ELinkList.h" //**▲02 线性表**//
/* 一元多项式类型定义 */
@@ -24,12 +26,17 @@ typedef ELinkList Polynomial;
*
* 根据输入的系数和指数创建项数为m的一元多项式
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreatPolyn(char path[], Polynomial *P, int m);
void CreatPolyn(Polynomial* P, int m, ...);
/*
* 销毁

View File

@@ -149,8 +149,8 @@ int main(int argc, char** argv) {
printf("████████ CreateList_Head \n");
{
LinkList L;
CreateList_Head(&L, 5, "TestData_Head.txt");
printf("█ 头插法建立单链表 L = ");
CreateList_Head("TestData_Head.txt", &L, 5);
ListTraverse(L, PrintElem);
}
PressEnterToContinue();
@@ -159,8 +159,8 @@ int main(int argc, char** argv) {
printf("████████ CreateList_Tail \n");
{
LinkList L;
CreateList_Tail(&L, 5, "TestData_Tail.txt");
printf("█ 尾插法建立单链表 L = ");
CreateList_Tail("TestData_Tail.txt", &L, 5);
ListTraverse(L, PrintElem);
}
PressEnterToContinue();

View File

@@ -384,105 +384,150 @@ void ListTraverse(LinkList L, void(Visit)(ElemType)) {
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Head(LinkList* L, int n, ...) {
int i;
LinkList p;
ElemType e;
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L == NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
for(i = 1; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个降序元素", n);
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p == NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
} else {
fclose(fp);
}
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
}
fclose(fp);
}
fclose(fp);
return OK;
}
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Tail(LinkList* L, int n, ...) {
int i;
LinkList p, q;
ElemType e;
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L==NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
for(i = 1, q = *L; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个升序元素", n);
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p==NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
q->next = p;
q = q->next;
} else {
fclose(fp);
}
q->next = NULL;
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
q->next = p;
q = q->next;
}
q->next = NULL;
fclose(fp);
}
q->next = NULL;
fclose(fp);
return OK;
}

View File

@@ -8,7 +8,9 @@
#define LINKLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供 malloc、realloc、free、exit 原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
/* 单链表元素类型定义 */
@@ -147,22 +149,31 @@ void ListTraverse(LinkList L, void(Visit)(ElemType));
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n);
Status CreateList_Head(LinkList* L, int n, ...);
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n);
Status CreateList_Tail(LinkList* L, int n, ...);
#endif

View File

@@ -34,105 +34,150 @@ void ListTraverse(LinkList L, void(Visit)(ElemType)) {
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Head(LinkList* L, int n, ...) {
int i;
LinkList p;
ElemType e;
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L == NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
for(i = 1; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个降序元素", n);
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p == NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
} else {
fclose(fp);
}
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
}
fclose(fp);
}
fclose(fp);
return OK;
}
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Tail(LinkList* L, int n, ...) {
int i;
LinkList p, q;
ElemType e;
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L==NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
for(i = 1, q = *L; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个升序元素", n);
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p==NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
q->next = p;
q = q->next;
} else {
fclose(fp);
}
q->next = NULL;
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
q->next = p;
q = q->next;
}
q->next = NULL;
fclose(fp);
}
q->next = NULL;
fclose(fp);
return OK;
}

View File

@@ -8,7 +8,9 @@
#define LINKLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
/* 单链表元素类型定义 */
@@ -40,22 +42,32 @@ void ListTraverse(LinkList L, void(Visit)(ElemType));
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n);
Status CreateList_Head(LinkList* L, int n, ...);
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n);
Status CreateList_Tail(LinkList* L, int n, ...);
#endif

View File

@@ -9,23 +9,23 @@ void PrintElem(ElemType e) {
int main(int argc, char** argv) {
LinkList La, Lb, Lc;
int m = 5;
printf("作为示例La长度设定为 %d Lb长度设定为 %d 创建La和Lb...\n", m, m);
CreateList_Head("TestData_Head.txt", &La, m);
int n = 5;
printf("作为示例La长度设定为 %d Lb长度设定为 %d 创建La和Lb...\n", n, n);
CreateList_Head(&La, n, "TestData_Head.txt");
printf("La = ");
ListTraverse(La, PrintElem);
CreateList_Tail("TestData_Tail.txt", &Lb, m);
CreateList_Tail(&Lb, n, "TestData_Tail.txt");
printf("Lb = ");
ListTraverse(Lb, PrintElem);
printf("归并La和Lb为Lc = ");
MergeList(&La, &Lb, &Lc);
ListTraverse(Lc, PrintElem);
return 0;
}

View File

@@ -10,10 +10,13 @@ void PrintElem(ElemType e) {
int main(int argc, char** argv) {
SLinkList space; // 备用空间
int S; // 静态链表
// S = (A-B)(B-A)
difference(space, &S, "TestData.txt");
printf("S = (A-B)(B-A) = ");
difference("TestData.txt", space, &S);
ListTraverse(space, S, PrintElem);
return 0;
}

View File

@@ -13,74 +13,112 @@
*
* 对集合A和集合B进行(A-B)(B-A)计算计算结果存入静态链表S
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void difference(char path[], SLinkList space, int* S) {
FILE* fp;
void difference(SLinkList space, int* S, ...) {
int m, n; // 集合A和集合B中元素数量
int j; // 循环计数器
int R; // 指向静态链表最后一个结点
int i, k, p;
int b; // 临时存储从集合B中读到的数据
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, S);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
// 初始化备用空间
InitSpace(space);
// 获取静态链表头结点
*S = Malloc(space);
// 让R执行静态链表最后的结点
R = *S;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
// 读取集合A和集合B的元素个数
ReadData(fp, "%d%d", &m, &n);
if(readFromConsole) {
printf("请输入集合A的元素个数");
scanf("%d", &m);
printf("请输入集合B的元素个数");
scanf("%d", &n);
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
ReadData(fp, "%d%d", &m, &n);
}
if(readFromConsole) {
printf("请输入 %d 个元素存入集合A", m);
}
// 录入集合A的数据
for(j = 1; j <= m; ++j) {
// 分配结点
i = Malloc(space);
// 输入集合A的元素值
ReadData(fp, "%d", &space[i].data);
if(readFromConsole) {
scanf("%d", &space[i].data);
} else {
ReadData(fp, "%d", &space[i].data);
}
// 将新结点插入到表尾
space[R].cur = i;
R = i;
}
// 尾结点的指针置空
space[R].cur = 0;
if(readFromConsole) {
printf("请输入 %d 个元素存入集合B", n);
}
// 录入集合B的数据
for(j = 1; j <= n; ++j) {
// 输入集合B的元素值
ReadData(fp, "%d", &b);
if(readFromConsole) {
scanf("%d", &b);
} else {
ReadData(fp, "%d", &b);
}
p = *S; // 指向静态链表头结点后续总是指向k的前一个位置
k = space[*S].cur; // 指向静态链表中的首个元素
// 在当前静态链表中查找是否存在b元素
while(k != space[R].cur && space[k].data != b) {
p = k;
k = space[k].cur;
}
// 如果该元素不存在,则加入静态链表
if(k == space[R].cur) {
i = Malloc(space);
space[i].data = b;
space[i].cur = space[R].cur;
space[R].cur = i;
// 如果该元素已存在,则需要移除
} else {
space[p].cur = space[k].cur;
@@ -90,6 +128,9 @@ void difference(char path[], SLinkList space, int* S) {
}
}
}
fclose(fp);
}
if(!readFromConsole) {
fclose(fp);
}
}

View File

@@ -8,8 +8,10 @@
#define DIFFERENCE_H
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SLinkList.h" //**▲02 线性表**//
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
#include "SLinkList.h" //**▲02 线性表**//
/*
* ████████ 算法2.17 ████████
@@ -18,11 +20,17 @@
*
* 对集合A和集合B进行(A-B)(B-A)计算计算结果存入静态链表S
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void difference(char path[], SLinkList space, int* S);
void difference(SLinkList space, int* S, ...);
#endif

View File

@@ -1,5 +1,7 @@
#include <stdio.h>
#include "MergeEList.h" //**▲02 线性表**//
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "MergeEList.h" //**▲02 线性表**//
// 测试函数,打印元素
void PrintElem(ElemType e) {
@@ -21,51 +23,81 @@ int Cmp(ElemType e1, ElemType e2) {
/*
* 尾插法创建链表
*
*
*【备注】
*
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件fp中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreateList_Tail(char path[], ELinkList* L) {
FILE* fp;
void CreateList_Tail(ELinkList* L, ...) {
int i, n;
ElemType e;
fp = fopen(path, "r");
if(fp == NULL) {
printf("文件打开失败...\n");
exit(ERROR);
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, L);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 读取指定集合中元素的数量
printf("请输入元素数量:");
scanf("%d", &n);
InitList(L);
printf("请输入 %d 个元素:", n);
for(i = 1; i <= n; i++) {
scanf("%d", &e);
ListInsert(L, i, e);
}
} else {
fp = fopen(path, "r");
if(fp == NULL) {
printf("文件打开失败...\n");
exit(ERROR);
}
// 读取指定集合中元素的数量
ReadData(fp, "%d", &n);
InitList(L);
for(i = 1; i <= n; i++) {
ReadData(fp, "%d", &e);
ListInsert(L, i, e);
}
fclose(fp);
}
// 读取指定集合中元素的数量
ReadData(fp, "%d", &n);
InitList(L);
for(i = 1; i <= n; i++) {
ReadData(fp, "%d", &e);
ListInsert(L, i, e);
}
fclose(fp);
}
int main(int argc, char** argv) {
ELinkList La, Lb, Lc;
printf("创建La和Lb以待测试...\n");
CreateList_Tail("TestData_La.txt", &La);
CreateList_Tail(&La, "TestData_La.txt");
printf("La= ");
ListTraverse(La, PrintElem);
CreateList_Tail("TestData_Lb.txt", &Lb);
CreateList_Tail(&Lb, "TestData_Lb.txt");
printf("Lb= ");
ListTraverse(Lb, PrintElem);
MergeEList(&La, &Lb, &Lc, Cmp);
printf("合并La和Lb为 Lc = ");
ListTraverse(Lc, PrintElem);
return 0;
}

View File

@@ -3,56 +3,56 @@
int main(int argc, char **argv) {
Polynomial Pa, Pb;
int m, n;
m = 5;
n = 6;
printf("████████ CreatPolyn \n");
{
printf("█ 作为示范,创建项数为 %d 的多项式Pa...\n", m);
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
printf("█ 作为示范,创建项数为 %d 的多项式Pb...\n", n);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pb, n, "TestData_Pb.txt");
}
PressEnterToContinue();
printf("████████ PrintPolyn \n");
{
printf("█ 一元多项式 Pa = ");
PrintPolyn(Pa);
printf("█ 一元多项式 Pb = ");
PrintPolyn(Pb);
}
PressEnterToContinue();
printf("████████ PolynLength \n");
{
printf("█ La 的项数为 %d Lb 的项数为 %d\n", PolynLength(Pa), PolynLength(Pb));
}
PressEnterToContinue();
printf("████████ AddPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
AddPolyn(&Pa, &Pb);
printf("█ Pa = Pa + Pb = ");
PrintPolyn(Pa);
}
PressEnterToContinue();
printf("████████ SubtractPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
SubtractPolyn(&Pa, &Pb);
@@ -61,11 +61,11 @@ int main(int argc, char **argv) {
}
PressEnterToContinue();
printf("████████ MultiplyPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
MultiplyPolyn(&Pa, &Pb);
@@ -73,7 +73,7 @@ int main(int argc, char **argv) {
PrintPolyn(Pa);
}
PressEnterToContinue();
return 0;
}

View File

@@ -16,40 +16,66 @@
*
* 根据输入的系数和指数创建项数为m的一元多项式
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreatPolyn(char path[], Polynomial* P, int m) {
FILE* fp;
void CreatPolyn(Polynomial* P, int m, ...) {
int i;
ElemType e;
Position h, q;
Link s;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, m);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
// 初始化一个线性链表存放一元多项式
InitList(P);
// 获取多项式头指针
h = GetHead(*P);
// 为头结点填充数据
e.coef = 0.0f;
e.expn = -1;
SetCurElem(h, e);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
if(!readFromConsole) {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
}
if(readFromConsole) {
printf("请输入 %d 个元素:\n", m);
}
// 依次录入m个有效项
for(i = 1; i <= m; i++) {
// 读取系数和指数信息临时存入e
ReadData(fp, "%f%d", &(e.coef), &(e.expn));
if(readFromConsole) {
printf("请输入第 %d 组系数和指数:", i);
scanf("%f%d", &(e.coef), &(e.expn));
} else {
ReadData(fp, "%f%d", &(e.coef), &(e.expn));
}
// 如果当前链表中不存在该指数项
if(LocateElem(*P, e, &q, Cmp) == FALSE && q != NULL) {
// 创建新结点
@@ -59,8 +85,10 @@ void CreatPolyn(char path[], Polynomial* P, int m) {
}
}
}
fclose(fp);
if(!readFromConsole) {
fclose(fp);
}
}
/*
@@ -94,21 +122,21 @@ void AddPolyn(Polynomial* Pa, Polynomial* Pb) {
Position qa, qb;
ElemType a, b;
float sum;
// ha、hb分别指向Pa、Pb头结点
ha = GetHead(*Pa);
hb = GetHead(*Pb);
// qa、qb分别指向Pa、Pb的当前结点
qa = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
// qa、qb均非空
while(qa && qb) {
// a和b为两表中当前比较元素
a = GetCurElem(qa);
b = GetCurElem(qb);
//比较当前元素的指数大小
switch(Cmp(a, b)) {
// 多项式Pa中当前结点的指数值较小
@@ -116,19 +144,19 @@ void AddPolyn(Polynomial* Pa, Polynomial* Pb) {
ha = qa;
qa = NextPos(*Pa, qa);
}
break;
// 两者数值相等
break;
// 两者数值相等
case 0: {
sum = a.coef + b.coef;
// 相加不能抵消时更新Pa结点的系数值
if(sum != 0.0) {
// 这里用SetCurElem()不合适,不如直接赋值
qa->data.coef = sum;
// ha后移
ha = qa;
//相加抵消时删除Pa中当前结点
} else {
// 删除ha后面的结点其实删的就是qa
@@ -136,41 +164,41 @@ void AddPolyn(Polynomial* Pa, Polynomial* Pb) {
// 释放被删除结点所占空间
FreeNode(&qa);
}
// 删除Pb中扫描过的结点
DelFirst(Pb, hb, &qb);
// 释放被删除结点所占空间
FreeNode(&qb);
// qa、qb均后移
qa = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
// 多项式Pb中当前结点的指数值较小
break;
// 多项式Pb中当前结点的指数值较小
case 1: {
// 摘下Pb当前结点
DelFirst(Pb, hb, &qb);
// 将摘下结点链入Pa中
InsFirst(Pa, ha, qb);
ha = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
break;
}//switch
}//while
// 若Pb还未扫描完将剩余项链接到Pa后
if(qb != NULL) {
Append(Pa, qb);
}
// 释放Pb头结点
FreeNode(&hb);
// 设置Pb为销毁状态
(*Pb).head = (*Pb).tail = NULL;
(*Pb).len = 0;
@@ -188,21 +216,21 @@ void SubtractPolyn(Polynomial* Pa, Polynomial* Pb) {
Position r;
ElemType a, b;
float sum;
// ha、hb分别指向Pa、Pb头结点
ha = GetHead(*Pa);
hb = GetHead(*Pb);
// qa、qb分别指向Pa、Pb的当前结点
qa = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
// qa、qb均非空
while(qa && qb) {
// a和b为两表中当前比较元素
a = GetCurElem(qa);
b = GetCurElem(qb);
// 比较当前元素的指数大小
switch(Cmp(a, b)) {
// 多项式Pa中当前结点的指数值较小
@@ -211,18 +239,18 @@ void SubtractPolyn(Polynomial* Pa, Polynomial* Pb) {
qa = NextPos(*Pa, ha);
}
break;
// 两者数值相等
// 两者数值相等
case 0: {
sum = a.coef - b.coef;
// 相减不能抵消时更新Pa结点的系数值
if(sum != 0.0) {
// 更新系数
qa->data.coef = sum;
// ha后移
ha = qa;
// 相减抵消时删除Pa中当前结点
} else {
// 删除ha后面的结点其实删的就是qa
@@ -230,49 +258,49 @@ void SubtractPolyn(Polynomial* Pa, Polynomial* Pb) {
// 释放被删除结点所占空间
FreeNode(&qa);
}
// 删除Pb中扫描过的结点
DelFirst(Pb, hb, &qb);
// 释放被删除结点所占空间
FreeNode(&qb);
// qa、qb均后移
qa = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
// 多项式Pb中当前结点的指数值较小
break;
// 多项式Pb中当前结点的指数值较小
case 1: {
// 摘下Pb当前结点
DelFirst(Pb, hb, &qb);
// 改变当前结点符号
qb->data.coef = -qb->data.coef;
// 将摘下结点链入Pa中
InsFirst(Pa, ha, qb);
ha = NextPos(*Pa, ha);
qb = NextPos(*Pb, hb);
}
break;
break;
}//switch
}//while
// 若Pb还未扫描完将剩余项的系数取反后链接到Pa后
if(qb != NULL) {
// 改变剩余项的符号
for(r = qb = 0; r != NULL; r = r->next) {
r->data.coef = -r->data.coef;
}
Append(Pa, qb);
}
// 释放Pb头结点
FreeNode(&hb);
// 设置Pb为销毁状态
(*Pb).head = (*Pb).tail = NULL;
(*Pb).len = 0;
@@ -291,45 +319,45 @@ void MultiplyPolyn(Polynomial* Pa, Polynomial* Pb) {
Position qa, qb;
Link s;
ElemType e;
// 获取两个多项式的长度
la = PolynLength(*Pa);
lb = PolynLength(*Pb);
// ha、hb分别指向Pa、Pb头结点
ha = GetHead(*Pa);
hb = GetHead(*Pb);
// 累加计算结果
InitList(&Pc);
// 遍历Pa中的元素
for(i = 1; i <= la; i++) {
// 存储临时计算结果
InitList(&Ptmp);
// 逐个摘下Pa中的结点
DelFirst(Pa, ha, &qa);
// 遍历Pb中所有结点与Pa中摘下的结点进行运算
for(j = 1, qb = NextPos(*Pb, hb); j <= lb; j++, qb = NextPos(*Pb, qb)) {
e.coef = qa->data.coef * qb->data.coef; //系数相乘
e.expn = qa->data.expn + qb->data.expn; //指数相加
// 创建新结点存储结算结果
MakeNode(&s, e);
// 添加到临时多项式
Append(&Ptmp, s);
}
// 将新的多项式累加到Pc上
AddPolyn(&Pc, &Ptmp);
}
// 将所有结果添加到Pa上
AddPolyn(Pa, &Pc);
// 销毁多项式Pb
DestroyPolyn(Pb);
}
@@ -345,13 +373,13 @@ void MultiplyPolyn(Polynomial* Pa, Polynomial* Pb) {
void PrintPolyn(Polynomial P) {
int i;
Link p;
p = P.head->next;
for(i = 1; i <= P.len; i++) {
if(p->data.coef == 0.0f) {
continue;
}
if(i == 1) {
printf("%g", p->data.coef);
} else {
@@ -363,18 +391,18 @@ void PrintPolyn(Polynomial P) {
printf("%g", -p->data.coef);
}
}
if(p->data.expn) {
printf("x");
if(p->data.expn != 1) {
printf("^%d", p->data.expn);
}
}
p = p->next;
}
printf("\n");
}
@@ -386,7 +414,7 @@ void PrintPolyn(Polynomial P) {
int Cmp(ElemType c1, ElemType c2) {
// 计算指数差
int i = c1.expn - c2.expn;
if(i < 0) {
return -1;
} else if(i == 0) {
@@ -395,3 +423,4 @@ int Cmp(ElemType c1, ElemType c2) {
return 1;
}
}

View File

@@ -8,7 +8,9 @@
#define POLYNOMIAL_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "ELinkList.h" //**▲02 线性表**//
/* 一元多项式类型定义 */
@@ -24,12 +26,17 @@ typedef ELinkList Polynomial;
*
* 根据输入的系数和指数创建项数为m的一元多项式
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreatPolyn(char path[], Polynomial *P, int m);
void CreatPolyn(Polynomial* P, int m, ...);
/*
* 销毁
@@ -89,3 +96,4 @@ void PrintPolyn(Polynomial P);
int Cmp(ElemType c1, ElemType c2);
#endif

View File

@@ -149,8 +149,8 @@ int main(int argc, char** argv) {
printf("████████ CreateList_Head \n");
{
LinkList L;
CreateList_Head(&L, 5, "TestData_Head.txt");
printf("█ 头插法建立单链表 L = ");
CreateList_Head("TestData_Head.txt", &L, 5);
ListTraverse(L, PrintElem);
}
PressEnterToContinue();
@@ -159,8 +159,8 @@ int main(int argc, char** argv) {
printf("████████ CreateList_Tail \n");
{
LinkList L;
CreateList_Tail(&L, 5, "TestData_Tail.txt");
printf("█ 尾插法建立单链表 L = ");
CreateList_Tail("TestData_Tail.txt", &L, 5);
ListTraverse(L, PrintElem);
}
PressEnterToContinue();

View File

@@ -384,105 +384,149 @@ void ListTraverse(LinkList L, void(Visit)(ElemType)) {
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Head(LinkList* L, int n, ...) {
int i;
LinkList p;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L == NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个降序元素", n);
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p == NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
} else {
fclose(fp);
}
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
}
fclose(fp);
}
fclose(fp);
return OK;
}
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Tail(LinkList* L, int n, ...) {
int i;
LinkList p, q;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L==NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个升序元素", n);
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p==NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
q->next = p;
q = q->next;
} else {
fclose(fp);
}
q->next = NULL;
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
q->next = p;
q = q->next;
}
q->next = NULL;
fclose(fp);
}
q->next = NULL;
fclose(fp);
return OK;
}

View File

@@ -8,7 +8,9 @@
#define LINKLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供 malloc、realloc、free、exit 原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
/* 单链表元素类型定义 */
@@ -147,22 +149,31 @@ void ListTraverse(LinkList L, void(Visit)(ElemType));
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n);
Status CreateList_Head(LinkList* L, int n, ...);
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n);
Status CreateList_Tail(LinkList* L, int n, ...);
#endif

View File

@@ -34,105 +34,149 @@ void ListTraverse(LinkList L, void(Visit)(ElemType)) {
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Head(LinkList* L, int n, ...) {
int i;
LinkList p;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L == NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个降序元素", n);
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p == NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
} else {
fclose(fp);
}
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
p->next = (*L)->next;
(*L)->next = p;
}
fclose(fp);
}
fclose(fp);
return OK;
}
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n) {
FILE* fp;
Status CreateList_Tail(LinkList* L, int n, ...) {
int i;
LinkList p, q;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
if(*L==NULL) {
exit(OVERFLOW);
}
(*L)->next = NULL;
va_start(ap, n);
path = va_arg(ap, char*);
va_end(ap);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 如果成功读取到输入数据
if(ReadData(fp, "%d", &e) == 1) {
if(readFromConsole) {
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输入%d个升序元素", n);
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
if(p==NULL) {
fclose(fp);
exit(OVERFLOW);
}
// 填充数据,并插入到链表中
p->data = e;
scanf("%d", &(p->data));
q->next = p;
q = q->next;
} else {
fclose(fp);
}
q->next = NULL;
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
return ERROR;
}
// 建立头结点
*L = (LinkList) malloc(sizeof(LNode));
(*L)->next = NULL;
for(i = 1, q = *L; i <= n; ++i) {
// 生成新结点
p = (LinkList) malloc(sizeof(LNode));
// 填充数据,并插入到链表中
ReadData(fp, "%d", &(p->data));
q->next = p;
q = q->next;
}
q->next = NULL;
fclose(fp);
}
q->next = NULL;
fclose(fp);
return OK;
}

View File

@@ -8,7 +8,9 @@
#define LINKLIST_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
/* 单链表元素类型定义 */
@@ -40,22 +42,31 @@ void ListTraverse(LinkList L, void(Visit)(ElemType));
*
* 头插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 另教材中的算法采用的是头插法所以此处的实现加了后缀_Head。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Head(char path[], LinkList* L, int n);
Status CreateList_Head(LinkList* L, int n, ...);
/*
* 尾插法创建链表
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
Status CreateList_Tail(char path[], LinkList* L, int n);
Status CreateList_Tail(LinkList* L, int n, ...);
#endif

View File

@@ -10,15 +10,15 @@ void PrintElem(ElemType e) {
int main(int argc, char** argv) {
LinkList La, Lb, Lc;
int m = 5;
int n = 5;
printf("作为示例La长度设定为 %d Lb长度设定为 %d 创建La和Lb...\n", m, m);
printf("作为示例La长度设定为 %d Lb长度设定为 %d 创建La和Lb...\n", n, n);
CreateList_Head("TestData_Head.txt", &La, m);
CreateList_Head(&La, n, "TestData_Head.txt");
printf("La = ");
ListTraverse(La, PrintElem);
CreateList_Tail("TestData_Tail.txt", &Lb, m);
CreateList_Tail(&Lb, n, "TestData_Tail.txt");
printf("Lb = ");
ListTraverse(Lb, PrintElem);

View File

@@ -11,8 +11,10 @@ int main(int argc, char** argv) {
SLinkList space; // 备用空间
int S; // 静态链表
// S = (A-B)(B-A)
difference(space, &S, "TestData.txt");
printf("S = (A-B)(B-A) = ");
difference("TestData.txt", space, &S);
ListTraverse(space, S, PrintElem);
return 0;

View File

@@ -13,18 +13,33 @@
*
* 对集合A和集合B进行(A-B)(B-A)计算计算结果存入静态链表S
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void difference(char path[], SLinkList space, int* S) {
FILE* fp;
void difference(SLinkList space, int* S, ...) {
int m, n; // 集合A和集合B中元素数量
int j; // 循环计数器
int R; // 指向静态链表最后一个结点
int i, k, p;
int b; // 临时存储从集合B中读到的数据
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, S);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
// 初始化备用空间
InitSpace(space);
@@ -35,14 +50,25 @@ void difference(char path[], SLinkList space, int* S) {
// 让R执行静态链表最后的结点
R = *S;
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
// 读取集合A和集合B的元素个数
if(readFromConsole) {
printf("请输入集合A的元素个数");
scanf("%d", &m);
printf("请输入集合B的元素个数");
scanf("%d", &n);
} else {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
ReadData(fp, "%d%d", &m, &n);
}
// 读取集合A和集合B的元素个数
ReadData(fp, "%d%d", &m, &n);
if(readFromConsole) {
printf("请输入 %d 个元素存入集合A", m);
}
// 录入集合A的数据
for(j = 1; j <= m; ++j) {
@@ -50,7 +76,11 @@ void difference(char path[], SLinkList space, int* S) {
i = Malloc(space);
// 输入集合A的元素值
ReadData(fp, "%d", &space[i].data);
if(readFromConsole) {
scanf("%d", &space[i].data);
} else {
ReadData(fp, "%d", &space[i].data);
}
// 将新结点插入到表尾
space[R].cur = i;
@@ -60,10 +90,18 @@ void difference(char path[], SLinkList space, int* S) {
// 尾结点的指针置空
space[R].cur = 0;
if(readFromConsole) {
printf("请输入 %d 个元素存入集合B", n);
}
// 录入集合B的数据
for(j = 1; j <= n; ++j) {
// 输入集合B的元素值
ReadData(fp, "%d", &b);
if(readFromConsole) {
scanf("%d", &b);
} else {
ReadData(fp, "%d", &b);
}
p = *S; // 指向静态链表头结点后续总是指向k的前一个位置
k = space[*S].cur; // 指向静态链表中的首个元素
@@ -91,5 +129,7 @@ void difference(char path[], SLinkList space, int* S) {
}
}
fclose(fp);
}
if(!readFromConsole) {
fclose(fp);
}
}

View File

@@ -8,8 +8,10 @@
#define DIFFERENCE_H
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SLinkList.h" //**▲02 线性表**//
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "Status.h" //**▲01 绪论**//
#include "SLinkList.h" //**▲02 线性表**//
/*
* ████████ 算法2.17 ████████
@@ -18,11 +20,16 @@
*
* 对集合A和集合B进行(A-B)(B-A)计算计算结果存入静态链表S
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void difference(char path[], SLinkList space, int* S);
void difference(SLinkList space, int* S, ...);
#endif

View File

@@ -1,5 +1,7 @@
#include <stdio.h>
#include "MergeEList.h" //**▲02 线性表**//
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "MergeEList.h" //**▲02 线性表**//
// 测试函数,打印元素
void PrintElem(ElemType e) {
@@ -21,32 +23,61 @@ int Cmp(ElemType e1, ElemType e2) {
/*
* 尾插法创建链表
*
*
*【备注】
*
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件fp中读取测试数据。
* 因而允许选择从预设的文件path中读取测试数据。
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreateList_Tail(char path[], ELinkList* L) {
FILE* fp;
void CreateList_Tail(ELinkList* L, ...) {
int i, n;
ElemType e;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
fp = fopen(path, "r");
if(fp == NULL) {
printf("文件打开失败...\n");
exit(ERROR);
va_start(ap, L);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
if(readFromConsole) {
// 读取指定集合中元素的数量
printf("请输入元素数量:");
scanf("%d", &n);
InitList(L);
printf("请输入 %d 个元素:", n);
for(i = 1; i <= n; i++) {
scanf("%d", &e);
ListInsert(L, i, e);
}
} else {
fp = fopen(path, "r");
if(fp == NULL) {
printf("文件打开失败...\n");
exit(ERROR);
}
// 读取指定集合中元素的数量
ReadData(fp, "%d", &n);
InitList(L);
for(i = 1; i <= n; i++) {
ReadData(fp, "%d", &e);
ListInsert(L, i, e);
}
fclose(fp);
}
// 读取指定集合中元素的数量
ReadData(fp, "%d", &n);
InitList(L);
for(i = 1; i <= n; i++) {
ReadData(fp, "%d", &e);
ListInsert(L, i, e);
}
fclose(fp);
}
@@ -55,11 +86,11 @@ int main(int argc, char** argv) {
printf("创建La和Lb以待测试...\n");
CreateList_Tail("TestData_La.txt", &La);
CreateList_Tail(&La, "TestData_La.txt");
printf("La= ");
ListTraverse(La, PrintElem);
CreateList_Tail("TestData_Lb.txt", &Lb);
CreateList_Tail(&Lb, "TestData_Lb.txt");
printf("Lb= ");
ListTraverse(Lb, PrintElem);

View File

@@ -10,10 +10,10 @@ int main(int argc, char **argv) {
printf("████████ CreatPolyn \n");
{
printf("█ 作为示范,创建项数为 %d 的多项式Pa...\n", m);
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
printf("█ 作为示范,创建项数为 %d 的多项式Pb...\n", n);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pb, n, "TestData_Pb.txt");
}
PressEnterToContinue();
@@ -38,8 +38,8 @@ int main(int argc, char **argv) {
printf("████████ AddPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
AddPolyn(&Pa, &Pb);
@@ -51,8 +51,8 @@ int main(int argc, char **argv) {
printf("████████ SubtractPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
SubtractPolyn(&Pa, &Pb);
@@ -64,8 +64,8 @@ int main(int argc, char **argv) {
printf("████████ MultiplyPolyn \n");
{
CreatPolyn("TestData_Pa.txt", &Pa, m);
CreatPolyn("TestData_Pb.txt", &Pb, n);
CreatPolyn(&Pa, m, "TestData_Pa.txt");
CreatPolyn(&Pb, n, "TestData_Pb.txt");
MultiplyPolyn(&Pa, &Pb);

View File

@@ -16,17 +16,32 @@
*
* 根据输入的系数和指数创建项数为m的一元多项式
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreatPolyn(char path[], Polynomial* P, int m) {
FILE* fp;
void CreatPolyn(Polynomial* P, int m, ...) {
int i;
ElemType e;
Position h, q;
Link s;
va_list ap;
FILE* fp;
char* path = NULL;
int readFromConsole; // 是否从控制台读取数据
va_start(ap, m);
path = va_arg(ap, char*);
va_end(ap);
// 如果没有文件路径信息,则从控制台读取输入
readFromConsole = path == NULL || strstr(path, "TestData") == NULL;
// 初始化一个线性链表存放一元多项式
InitList(P);
@@ -39,16 +54,27 @@ void CreatPolyn(char path[], Polynomial* P, int m) {
e.expn = -1;
SetCurElem(h, e);
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
if(!readFromConsole) {
// 打开文件,准备读取测试数据
fp = fopen(path, "r");
if(fp == NULL) {
exit(ERROR);
}
}
if(readFromConsole) {
printf("请输入 %d 个元素:\n", m);
}
// 依次录入m个有效项
for(i = 1; i <= m; i++) {
// 读取系数和指数信息临时存入e
ReadData(fp, "%f%d", &(e.coef), &(e.expn));
if(readFromConsole) {
printf("请输入第 %d 组系数和指数:", i);
scanf("%f%d", &(e.coef), &(e.expn));
} else {
ReadData(fp, "%f%d", &(e.coef), &(e.expn));
}
// 如果当前链表中不存在该指数项
if(LocateElem(*P, e, &q, Cmp) == FALSE && q != NULL) {
@@ -60,7 +86,9 @@ void CreatPolyn(char path[], Polynomial* P, int m) {
}
}
fclose(fp);
if(!readFromConsole) {
fclose(fp);
}
}
/*

View File

@@ -8,7 +8,9 @@
#define POLYNOMIAL_H
#include <stdio.h>
#include <stdlib.h> //提供malloc、realloc、free、exit原型
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供 strstr 原型
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include "ELinkList.h" //**▲02 线性表**//
/* 一元多项式类型定义 */
@@ -24,12 +26,17 @@ typedef ELinkList Polynomial;
*
* 根据输入的系数和指数创建项数为m的一元多项式
*
*
*【备注】
*
* 教材中默认从控制台读取数据。
* 这里为了方便测试,避免每次运行都手动输入数据,
* 因而选择从预设的文件path中读取测试数据
* 因而允许选择从预设的文件path中读取测试数据
*
* 如果需要从控制台读取数据,则不需要填写可变参数,
* 如果需要从文件中读取数据,则需要在可变参数中填写文件名信息(文件名中需要包含子串"TestData")。
*/
void CreatPolyn(char path[], Polynomial *P, int m);
void CreatPolyn(Polynomial* P, int m, ...);
/*
* 销毁

Binary file not shown.

Binary file not shown.