实验题目一
一、单链表基本运算
【问题描述】
设计并实现线性表的单链表存储和运算。
【基本要求】
实现单链表的插入、删除和遍历运算,每种操作用一个函数实现。
插入操作:将一个新元素插入表中指定序号的位置。
删除操作:将指定序号的元素从表中删除。
遍历操作:从表头按次序输入所有元素的值,若是空表,则输出信息“empty list!”。
【实现提示】
程序运行时,首先在main函数中创建空的、带头结点的单链表。然后多次调用实现插入操作的函数(每次都将元素在序号1位置上插入),将元素依次插入表中,最后调用实现遍历操作的函数输出所有元素。之后再多次调用实现删除操作的函数将表还原为空表(每次都删除第1个元素,每删除一个元素后,将表中剩余元素都输出一次)。
【测试数据】
输入数据:1 2 3 4 5 0(为0时结束,0不存入链表)
第一次输出:5 4 3 2 1
第二次输出:4 3 2 1
第三次输出:3 2 1
第四次输出:2 1
第五次输出:1
第六次输出:empty list!
/*
* Name: 数据结构上机题目1-1.cpp
* Purpose: 单链表基本运算
* Author: Zhang
* Date: 2021/11/05
*/
#include <stdio.h>
#include <stdlib.h> //包含malloc函数。malloc——分配内存块,但不对内存块进行初始化;
typedef int DataType;
typedef struct node
{
DataType data;
struct node* link;
} LinkNode, * LinkList, * LinkList_nh;
void initList(LinkList& first) //目的:对带头结点的单链表进行初始化并置空;算法调用方式:initList(first)
{
first = (LinkNode*)malloc(sizeof(LinkNode));
first->link = NULL;
}//输入:单链表表头指针:first;输出:初始化后的单链表
void printList(LinkList& first) //目的:按顺序输出一个带头结点的单链表的所有元素的值;算法调用方式:printList(first);
{
for (LinkNode* p = first->link; p != NULL; p = p->link)
{
if (p->link==NULL) //最后一位后不加空格字符;
printf("%d", p->data);
else
printf("%d ", p->data);
}
printf("\n");
}//输入:单链表表头指针:first;输出:顺序输出链表各元素的值;
bool Insert(LinkList& first, int i, DataType x) //目的:把一个新元素x插入带头结点单链表的第i个(1<=i<=n)位置;算法调用方式:bool succ = Insert(first,i,x)
{
if (i < 0)
return false; //若i不合理则返回false;
LinkNode* p = first->link, * pr = first; //p指向第一个结点;
int k = 1; //p指向第一个结点;
while (p != NULL && k < i) //循环找第i个结点;
{
pr = p;
p = p->link;
k++;
} //pr指向p紧前结点,k为结点计数;
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode)); //创建一个新结点;
s->data = x;
s->link = p;
pr->link = s; //以上三行将*s链接在*pr之后;
return true; //插入成功;
}//输入:单链表表头指针:first,元素序号:i,待插入元素值:x;输出:在指定结点插入元素值x后的单链表first;
//若插入成功,函数返回true;若插入失败,函数返回false;
bool Remove(LinkList& first, int i) //目的:删除带头结点单链表的第i个(1<=i<=n)结点;算法调用方式:bool succ = Remove(first,i)
{
if (i < 0)
return false; //i太小,删除失败;
LinkNode* p = first->link, * pr = first;
int k = 1; //以上两行定位于第i个结点;
while (p != NULL && k < i) //循链找第i个结点;
{
pr = p;
p = p->link;
k++;
} //pr指向p紧前结点,k为结点计数;
if (p == NULL)
return false; //i太大,删除失败;
pr->link = p->link; //重新拉链,将被删结点从链中摘下;
free(p); //释放结点;
return true; //删除成功;
}//输入:单链表表头指针:first,元素序号:i;输出:删除该元素的值和删除后的单链表first;
//若删除成功,函数返回true;若删除失败,函数返回false;
int main(void)
{
LinkNode* p; //声明单链表表头指针:p
initList(p); //初始化p;
int input = 1; //假定input为1以便于接下来的判断;
while (input != 0) //当输入为0时结束循环,0不存入链表;
{
scanf("%d", &input); //把输入的数据存入input;
if (input != 0) //当input不为0时,存入链表;
bool succ = Insert(p, 1, input); //把一个符合条件的新元素input插入带头结点单链表的第1个位置(即头结点插入)
}
while (p->link != NULL) //当链表不为空时;
{
printList(p); //顺序输出链表各元素的值;
bool succ = Remove(p, 1); //删除带头结点单链表的第1个结点(删除头结点);
if (p->link == NULL) //删除链表完毕后,输出:empty list!
{
printf("empty list!\n");
break; //终止循环;
}
}
return 0; //主函数main返回值为0;
}
三、一元多项式相加、减运算器
本题目已完成调试!感谢梦里清扬路同学提供的帮助!!!(2021年11月24日)
【问题描述】
设计一个一元稀疏多项式简单计算器。
【基本要求】
一元稀疏多项式简单计算器的基本功能:
(1)输入并建立多项式的单向链表存储;
(2)输出多项式,形式为一个整数序列:,其中,n是多项式的项数,c i,e i分别是第i项的系数和指数,序列按指数降序排列;
(3)多项式A(x)和B(x)相加得到多项式C(x),输出C(x);
(4)多项式A(x)和B(x)相减得到多项式D(x),输出D(x)。
【测试数据】
【实现提示】
用带头结点的单链表存储多项式,多项式的项数放入头结点中。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define maxSize //项数最大个数;
typedef struct node //多项式结点的定义;
{
double coef; //系数;
int exp; //指数;
struct node* link;
}Term, * Polynomial; //多项式的类型定义;
void initList(Polynomial& A) //多项式初始化,并置空;
{
A = (Term*)malloc(sizeof(Term));
A->link = NULL;
}
void Input(Polynomial& A, double C[], int E[], int n)
{
//从系数数组C[n]和指数数组E[n]输入一元多项式的各项,创建一个按降幂方式排列的一元多项式A。要求调用此函数前PL已存在且已置空;
//算法调用方式:Input(Polynomial& A,double C[], int E[], int n);
//输入:已初始化的多项式链表A,系数数组E,多项式的项数n;
//输出:创建完成的按降幂排列的多项式链表A;
Polynomial newTerm, p, pr;
for (int i = 0; i < n; i++) //输入各项的系数和指数;
{
p = A->link;
pr = A; //按降幂查找新项插入位置;
while (p != NULL && p->exp > E[i])
{
pr = p;
p = p->link;
}
if (p != NULL && p->exp == E[i]) //已有指数相等的项,不插入;
//printf("已有与指数%d相等的项,输入作废\n",E[i]);
p->coef = p->coef + C[i];
else
{
newTerm = (Term*)malloc(sizeof(Term)); //创建新结点;
newTerm->coef = C[i];
newTerm->exp = E[i];
newTerm->link = p;
pr->link = newTerm; //链入并保持项指数降序;
}
}
}
void Output(Polynomial& A)
{
//算法调用方式:Output(A);
//输入:多项式链表A;
//输出:按降幂输出多项式链表A;
Polynomial p = A->link;
if (p == NULL)
printf("0");
bool h = 1; //最初不输出"+"的标识;
while (p != NULL)
{
if (h == 1)
{
if (p->coef < 0) //第一项系数小于零输出"-";
printf("-");
h = 0;
}
else //非第一项输出系数符号;
{
if (p->coef > 0)
printf("+");
else
printf("-");
}
if (p->exp == 0 || fabs(p->coef) != 1)
printf("%g", fabs(p->coef)); //输出项的系数;
switch (p->exp) //输出项的指数;
{
case 0: //常数项不输出指数;
break;
case 1: //一次项仅输出"X";
printf("X");
break;
default: //高次项输出"X^指数";
printf("X^%d", p->exp);
break;
}
p = p->link; //下一项;
}
printf("\n");
}
void ADD(Polynomial& A, Polynomial& B, Polynomial& C)
{
//计算C=A+B;
//算法调用方式:ADD(A,B,C);
//输入:有两个按降幂排列的多项式链表A和B,第三个多项式链表C也已经初始化;
//输出:多项式A+B的结果存入升幂排列的多项式链表C;
Polynomial p, q, r, s;
double temp;
r = C;
p = A->link;
q = B->link;
while (p != NULL && q != NULL) //两两比较;
{
if (p->exp == q->exp) //对应指数相等;
{
temp = p->coef + q->coef; //系数相加;
if (fabs(temp) > 0.001) //相加后系数不为0;
{
s = (Term*)malloc(sizeof(Term));
r->link = s;
r = r->link;
r->coef = temp;
r->exp = p->exp;
}
p = p->link;
q = q->link;
}
else //对应项指数不等;
{
s = (Term*)malloc(sizeof(Term));
r->link = s;
r = r->link; //创建新项,r是C链尾指针;
if (p->exp > q->exp) //p指数大;
{
r->coef = p->coef;
r->exp = p->exp;
p = p->link; //p指向A链下一个结点;
}
else //q指数大;
{
r->coef = q->coef;
r->exp = q->exp;
q = q->link; //q指向B链下一个结点;
}
}
}
p = (p != NULL) ? p : q; //p指向剩余链的地址;
while (p != NULL) //处理链剩余部分;
{
if (p->coef == 0) //如果该结点的系数为0,跳过该结点;
p = p->link;
else
{
r->link = (Term*)malloc(sizeof(Term));
r = r->link;
r->coef = p->coef;
r->exp = p->exp;
p = p->link;
}
}
r->link = NULL;
}
void SUB(Polynomial& A, Polynomial& B, Polynomial& C)
{
//计算C=A-B;
//算法调用方式:SUB(A,B,C);
//输入:有两个按降幂排列的多项式链表A和B,第三个多项式链表C也已经初始化;
//输出:多项式A-B的结果存入降幂排列的多项式链表C;
Polynomial p, q, r;
p = A->link;
q = B->link;
r = C;
while (p != NULL && q != NULL) //两多项式未扫描完;
{
if (p->exp > q->exp) //A多项式当前项指数大;
{
r->link = (Term*)malloc(sizeof(Term));
r = r->link;
r->coef = p->coef;
r->exp = p->exp;
p = p->link;
}
else if (p->exp < q->exp) //B多项式当前项指数大;
{
r->link = (Term*)malloc(sizeof(Term));
r = r->link;
r->coef = -q->coef;
r->exp = q->exp;
q = q->link;
}
else //A、B当前项指数相等;
{
if (fabs(p->coef - q->coef) > 0.001) //系数相减不为0存入C;
{
r->link = (Term*)malloc(sizeof(Term));
r = r->link;
r->coef = p->coef - q->coef;
r->exp = p->exp;
}
p = p->link;
q = q->link;
}
}
if (p != NULL) //p指向A中未处理完链;
{
while (p != NULL) //处理未处理完链;
{
if (p->coef == 0) //如果该结点的系数为0,跳过该结点;
p = p->link;
else
{
r->link = (Term*)malloc(sizeof(Term));
r = r->link;
r->coef = p->coef;
r->exp = p->exp;
p = p->link;
}
}
r->link = NULL;
}
else //q指向B中未处理完链;
{
while (q != NULL) //处理未处理完链;
{
if (q->coef == 0) //如果该结点的系数为0,跳过该结点;
q = q->link;
else
{
r->link = (Term*)malloc(sizeof(Term));
r = r->link;
r->coef = -q->coef;
r->exp = q->exp;
q = q->link;
}
}
r->link = NULL;
}
}
int main(void)
{
int n;
printf("请输入多项式链表A的项数:");
scanf_s("%d", &n);
int EA[100]={0};
double CA[100]={0.0};
printf("请输入多项式链表A的系数和指数:");
for (int i = 0; i < n; i++)
{
scanf_s("%lf %d", &CA[i], &EA[i]);
}
Polynomial A = NULL; //建立链表A;
initList(A); //初始化链表A;
Input(A, CA, EA, n); //把数组里面存的系数和指数输入链表A;
int m;
printf("请输入多项式链表B的项数:");
scanf_s("%d", &m);
int EB[100]={0};
double CB[100]={0.0};
printf("请输入多项式链表B的系数和指数:");
for (int i = 0; i < m; i++)
{
scanf_s("%lf %d", &CB[i], &EB[i]);
}
Polynomial B = NULL; //建立链表B;
initList(B); //初始化链表B;
Input(B, CB, EB, m); //把数组里面存的系数和指数输入链表B;
printf("多项式A(x)=");
Output(A);
printf("多项式B(x)=");
Output(B);
Polynomial C = NULL; //建立链表C;
initList(C); //初始化链表C;
Polynomial D = NULL; //建立链表D;
initList(D); //初始化链表D;
ADD(A, B, C);
SUB(A, B, D);
printf("多项式A(x)与多项式B(x)相加后得到的多项式C(x)=");
Output(C);
printf("多项式A(x)与多项式B(x)相减后得到的多项式D(x)=");
Output(D);
return 0;
}
参考文献
[1] 殷人昆作. 清华大学计算机系列教材 数据结构算法解析.[M] 北京:清华大学出版社, 2021.04.