實驗說明
數據結構實驗一 線性表的實驗——線性表的應用
一、實驗目的
通過本實驗使學生了解線性表的一種簡單應用,熟悉線性表順序存儲與鏈式存儲的特性,特別訓練學生編程靈活控制鏈表的能力,為今后編程控制更為復雜的數據結構奠定基礎。
二、實驗內容
1.用順序表和鏈表分別分別編程實現教材中例子2-1與2-2。要求:
(1)只能用C語言編程實現;(2)完全保持書中算法2.1與算法2.2形式,不允許有任何變化,除非語法上不允許;
所調用各函數參照書中19頁的功能描述,其中函數名、參數個數及性質、函數功能必須與書中完全一致,不能有變化。
2.利用線性表表示一元多項式完成多項式的加、減、乘、求導、求值運算。要求:
(1)輸入的一元多項式可以采用只輸入各項的系數與指數這種簡化的方式。如對於多項式2x2+6x5,輸入可為: 2,2 6,5 這樣的簡單形式。
(2)遇到有消項時應當處理,如2x2+6x5與3x2-6x5進行相加時,結果為5*x^2。
(3)當給定x的值時,能計算表達式相加或相減的結果。
(4)操作的結果放入一個新線性表中,原來的兩個表達式存儲表示不變,也可以不是產生新的線性表,而是將兩上線性表合並為一個。
(5)要求程序功能模塊划分合理(每個函數功能單一、可重用性好),使用空間盡可能少,算法盡可能高效。
實驗報告
1.實現功能描述
使用線性表表示一元多項式完成多項式的加、減,乘,求導、求值運算。
2.方案比較與選擇
(1)因為使用的是線性表,所以主要方案有數組法和鏈表法。
(2)從時間復雜度來說,使用數組法更優;從空間復雜度來說,鏈表法更優。因為數組法是指定好空間的,若式子大小超出設置大小,那程序必然出錯;若式子大小小於設置大小,那就意味着有多余的空間被浪費了。綜合來講,若計算式子較為龐大,使用鏈表法更佳;相反,若計算式子較小,數組法更佳。
3.設計算法描述
(1)單個項式的數據存儲使用了結構體,數組法是在一個結構體中定義兩個一維數組;鏈表法是通過一個結構體作為一個節點,通過next指針連接起來。
(2)進行模塊划分,給出功能組成框圖。形式如下:
(3)基本功能模塊:
①初始化多項式
②輸入多項式
③選擇運算方法
④合並同類項
⑤加減法運算
⑥乘法運算
⑦求導運算
⑧求值運算
⑨把多項式A,B存入多項式C中
⑩檢查多項式長度
⑪排序
⑫顯示多項式
⑬輸出多項式內容
(4)用流程圖描述關鍵算法:
4.算法實現(即完整源程序,帶注解)
(1)數組法:
點擊查看詳細內容
#include <stdio.h>
#include <math.h>
#define OK 0
#define ERROR 1
#define MAXSIZE 20
int initialization(struct Polynomial* num);
int inputPolynomial(char ch, struct Polynomial* num);
int choseOperation(void);
int combiningLikeTerms(struct Polynomial* num);
int additionORsubtraction(struct Polynomial* numA, struct Polynomial* numB, struct Polynomial* numC, int flag);
int multiplication(struct Polynomial* numA, struct Polynomial* numB, struct Polynomial* numC);
int derivation(struct Polynomial* numA, struct Polynomial* numC);
double evaluation(struct Polynomial* num, double value);
int mySave(struct Polynomial* numA, struct Polynomial* numB, struct Polynomial* numC, int flag);
int checkPolynomialLength(struct Polynomial* num);
int myBubbleSort(struct Polynomial* num);
int showPolynomial(char ch, struct Polynomial* num, int operation);
int printPolynomial(char ch, struct Polynomial* num);
struct Polynomial
{
int length;
double number[MAXSIZE];
int power[MAXSIZE];
};
int main(void)
{
struct Polynomial numA, numB, numC;
int operation = 0, temp;
double value, result = 0;
printf("此程序的功能是:對一元多項式進行簡單計算\n");
initialization(&numA);
initialization(&numB);
initialization(&numC);
while (!operation) {
operation = choseOperation();
}
printf("\n請輸入式子A的項數:");
scanf("%d", &temp);
if (temp < 0 || temp > MAXSIZE) {
printf("指定項數不在有效范圍內!");
return ERROR;
}
else {
numA.length = temp;
inputPolynomial('A', &numA);
}
if (operation != 4 && operation != 5) {
printf("\n請輸入式子B的項數:");
scanf("%d", &temp);
if (temp < 0 || temp > MAXSIZE) {
printf("指定項數不在有效范圍內!");
return ERROR;
}
else {
numB.length = temp;
inputPolynomial('B', &numB);
}
printf("\n");
}
switch (operation)
{
default:
break;
case 1:
additionORsubtraction(&numA, &numB, &numC, 1);
break;
case 2:
additionORsubtraction(&numA, &numB, &numC, -1);
break;
case 3:
multiplication(&numA, &numB, &numC);
break;
case 4:
derivation(&numA, &numC);
break;
case 5:
printf("請輸入x的值:");
scanf("%lf", &value);
numC.number[0] = evaluation(&numA, value);
numC.power[0] = 0;
numC.length = 1;
break;
}
showPolynomial('A', &numA, operation);
if (operation != 4 && operation != 5) {
showPolynomial('B', &numB, operation);
}
showPolynomial('C', &numC, operation);
return OK;
}
//初始化多項式
int initialization(struct Polynomial* num) {
int i;
num->length = 0;
for (i = 0; i < MAXSIZE; i++) {
num->number[i] = 0;
num->power[i] = 0;
}
return OK;
}
//輸入多項式
int inputPolynomial(char ch, struct Polynomial* num) {
int i;
if (num->length != 0) {
printf("請依項輸入式子%c(系數a,冪a 系數b,冪b...):", ch);
for (i = 0; i < num->length; i++) {
scanf("%lf,%d", &num->number[i], &num->power[i]);
}
}
return OK;
}
//選擇運算方法
int choseOperation(void) {
int operation = 0, flag;
printf("\n請選擇運算方法(1加法,2減法,3乘法,4求導,5代入x求值):");
scanf("%d", &flag);
if (flag >= 1 && flag <= 5) {
operation = flag;
}
else {
printf("選擇無效!\n");
}
return operation;
}
//合並同類項
int combiningLikeTerms(struct Polynomial* num) {
int i, j;
for (i = 0; i < num->length - 1; i++) {
for (j = i + 1; j < num->length; j++) {
if (num->power[i] == num->power[j]) {
if (num->number[i] != 0 && num->number[j] != 0) {
num->number[i] += num->number[j];
num->number[j] = 0;
}
}
}
}
return OK;
}
//加減法運算
int additionORsubtraction(struct Polynomial* numA, struct Polynomial* numB, struct Polynomial* numC, int flag) {
mySave(numA, numB, numC, flag);
combiningLikeTerms(numC);
checkPolynomialLength(numC);
return OK;
}
//乘法運算
int multiplication(struct Polynomial* numA, struct Polynomial* numB, struct Polynomial* numC) {
int length = 0, i, j;
for (i = 0; i < numA->length; i++) {
for (j = 0; j < numB->length; j++) {
numC->number[length] = numA->number[i] * numB->number[j];
numC->power[length++] = numA->power[i] + numB->power[j];
}
}
numC->length = length;
combiningLikeTerms(numC);
return OK;
}
//求導運算
int derivation(struct Polynomial* numA, struct Polynomial* numC){
int i;
for (i = 0; i < numA->length; i++) {
if (numA->power[i] != 0) {
numC->number[i] = numA->number[i] * numA->power[i];
numC->power[i] = numA->power[i] - 1;
}
else {
numC->number[i] = 0;
numC->power[i] = 0;
}
}
numC->length = numA->length;
combiningLikeTerms(numC);
return OK;
}
//求值運算
double evaluation(struct Polynomial* num, double value){
int i;
double result = 0;
for (i = 0; i < num->length; i++) {
result = result + num->number[i] * pow(value, (double)num->power[i]);
}
return result;
}
//把numA和numB全部存進numC
int mySave(struct Polynomial* numA, struct Polynomial* numB, struct Polynomial* numC, int flag) {
int count = 0, i;
for (i = 0; i < numA->length || i < numB->length; i++) {
if (numA->number[i] != 0 && i < numA->length) {
numC->number[count] = numA->number[i];
numC->power[count++] = numA->power[i];
}
if (numB->number[i] != 0 && i < numB->length) {
numC->number[count] = flag * numB->number[i];
numC->power[count++] = numB->power[i];
}
}
numC->length = count;
return OK;
}
//在additionORsubtraction函數中,可能導致多項式長度不正確
int checkPolynomialLength(struct Polynomial* num) {
int length = 0, i;
for (i = 0; i < num->length; i++) {
if (num->number[i] != 0){
length++;
}
}
num->length = length;
return OK;
}
//排序
int myBubbleSort(struct Polynomial* num){
int i, j;
double temp;
for (i = 0; i < num->length - 1; i++) {
for (j = i + 1; j < num->length; j++) {
if (num->power[i] > num->power[j]) {
if (num->number[i] == 0 || num->number[j] == 0) {
continue;
}
temp = num->number[i];
num->number[i] = num->number[j];
num->number[j] = temp;
temp = num->power[i];
num->power[i] = num->power[j];
num->power[j] = temp;
}
else if (num->power[i] == num->power[j]) {
if (num->number[i] == 0 || num->number[j] == 0) {
continue;
}
if (num->number[i] > num->number[j]) {
temp = num->number[i];
num->number[i] = num->number[j];
num->number[j] = temp;
}
}
}
}
return OK;
}
//顯示多項式
int showPolynomial(char ch, struct Polynomial* num, int operation) {
myBubbleSort(num);
switch (ch)
{
case 'C':
switch (operation)
{
case 1:
printf("加法的");
break;
case 2:
printf("減法的");
break;
case 3:
printf("乘法的");
break;
case 4:
printf("求導的");
break;
case 5:
printf("求值的");
break;
default:
break;
}
printf("計算結果為:");
printPolynomial('C', num);
break;
default:
printf("多項式%c 的內容為:", ch);
printPolynomial(ch, num);
break;
}
return OK;
}
//輸出多項式內容
int printPolynomial(char ch, struct Polynomial* num) {
int flag1 = 0, flag2 = 0, i;
for (i = 0; i < num->length; i++){
if (num->number[i] > 0 && i != 0 && flag2 == 1) {
printf("+");
flag1++;
}
if (num->number[i] != 0 && num->power[i] != 0) {
printf("%gx^%d", num->number[i], num->power[i]);
flag1++;
flag2 = 1;
}
else if(num->number[i] != 0 && num->power[i] == 0) {
printf("%g", num->number[i]);
flag1++;
}
}
if (flag1 == 0){
printf("0");
}
if (ch == 'A' || ch == 'B') {
printf("\n");
}
return OK;
}
(2)鏈表法:
點擊查看詳細內容
#include <stdio.h>
#include <math.h>
#define OK 0
#define ERROR 1
int initialization(struct PolynomialHead* num);
int inputPolynomial(char ch, struct PolynomialHead *polynomial);
int choseOperation(void);
int combiningLikeTerms(struct PolynomialHead* C);
int additionORsubtraction(struct PolynomialHead* A, struct PolynomialHead* B, struct PolynomialHead* C, int flag);
int multiplication(struct PolynomialHead* A, struct PolynomialHead* B, struct PolynomialHead* C);
int derivation(struct PolynomialHead* A, struct PolynomialHead* C);
double evaluation(struct PolynomialHead* A, double value);
int mySave(struct PolynomialHead* A, struct PolynomialHead* B, struct PolynomialHead* C, int flag);
int checkPolynomialLength(struct PolynomialHead* C);
int myBubbleSort(struct PolynomialHead* C);
int showPolynomial(char ch, struct PolynomialHead* num, int operation);
int printPolynomial(char ch, struct PolynomialHead* C);
typedef struct PolynomialHead
{
int length;
struct Polynomial* next;
}PolynomialHead;
struct Polynomial
{
double number;
int power;
struct Polynomial* next;
};
int main(void)
{
PolynomialHead A, B, C;
struct Polynomial numC;
int operation = 0, temp;
double value, result = 0;
printf("此程序的功能是:對一元多項式進行簡單計算\n");
initialization(&A);
initialization(&B);
initialization(&C);
while (!operation) {
operation = choseOperation();
}
printf("\n請輸入式子A的項數:");
scanf("%d", &temp);
if (temp < 0) {
printf("指定項數不在有效范圍內!");
return ERROR;
}
else {
A.length = temp;
inputPolynomial('A', &A);
}
if (operation != 4 && operation != 5) {
printf("\n請輸入式子B的項數:");
scanf("%d", &temp);
if (temp < 0) {
printf("指定項數不在有效范圍內!");
return ERROR;
}
else {
B.length = temp;
inputPolynomial('B', &B);
}
printf("\n");
}
switch (operation)
{
default:
break;
case 1:
additionORsubtraction(&A, &B, &C, 1);
break;
case 2:
additionORsubtraction(&A, &B, &C, -1);
break;
case 3:
multiplication(&A, &B, &C);
break;
case 4:
derivation(&A, &C);
break;
case 5:
printf("請輸入x的值:");
scanf("%lf", &value);
numC.number = evaluation(&A, value);
numC.power = 0;
C.next = &numC;
C.length = 1;
break;
}
showPolynomial('A', &A, operation);
if (operation != 4 && operation != 5) {
showPolynomial('B', &B, operation);
}
showPolynomial('C', &C, operation);
return OK;
}
//初始化多項式
int initialization(struct PolynomialHead* num) {
num->length = 0;
num->next = NULL;
return OK;
}
//輸入多項式
int inputPolynomial(char ch, struct PolynomialHead* polynomial) {
int i;
struct Polynomial *p1, *p2;
if (polynomial->length != 0) {
printf("請依項輸入式子%c(系數a,冪a 系數b,冪b...):", ch);
for (i = 0; i < polynomial->length; i++) {
p1 = (struct Polynomial*)malloc(sizeof(struct Polynomial) * polynomial->length);
scanf("%lf,%d", &p1->number, &p1->power);
if (i == 0) {
polynomial->next = p1;
}
else {
p2->next = p1;
}
p2 = p1;
}
p2->next = NULL;
}
return OK;
}
//選擇運算方法
int choseOperation(void) {
int operation = 0, flag;
printf("\n請選擇運算方法(1加法,2減法,3乘法,4求導,5代入x求值):");
scanf("%d", &flag);
if (flag >= 1 && flag <= 5) {
operation = flag;
}
else {
printf("選擇無效!\n");
}
return operation;
}
//合並同類項
int combiningLikeTerms(struct PolynomialHead* C) {
struct Polynomial *numi, *numj;
int i, j;
for (i = 0, numi = C->next; i < C->length - 1; i++, numi = numi->next) {
for (j = i + 1, numj = numi->next; j < C->length; j++, numj = numj->next) {
if (numi->power == numj->power) {
if (numi->number != 0 && numj->number != 0) {
numi->number += numj->number;
numj->number = 0;
}
}
}
}
return OK;
}
//加減法運算
int additionORsubtraction(struct PolynomialHead* A, struct PolynomialHead* B, struct PolynomialHead* C, int flag) {
mySave(A, B, C, flag);
combiningLikeTerms(C);
checkPolynomialLength(C);
return OK;
}
//乘法運算
int multiplication(struct PolynomialHead* A, struct PolynomialHead* B, struct PolynomialHead* C){
struct Polynomial *numA, *numB;
struct Polynomial *temp, *temp2;
int i, j, length = 0;
for (i = 0, numA = A->next; i < A->length; i++, numA = numA->next) {
for (j = 0, numB = B->next; j < B->length; j++, numB = numB->next) {
temp = (struct Polynomial*)malloc(sizeof(struct Polynomial));
temp->number = numA->number * numB->number;
temp->power = numA->power + numB->power;
if (length == 0) {
C->next = temp;
}
else {
temp2->next = temp;
}
temp2 = temp;
length++;
}
}
C->length = length;
combiningLikeTerms(C);
return OK;
}
//求導運算
int derivation(struct PolynomialHead* A, struct PolynomialHead* C){
int i, length = 0;
struct Polynomial *numA, *temp, *temp2;
for (i = 0, numA = A->next; i < A->length; i++, numA = numA->next) {
temp = (struct Polynomial*)malloc(sizeof(struct Polynomial));
if (numA->power != 0) {
temp->number = numA->number * numA->power;
temp->power = numA->power - 1;
}
else {
temp->number = 0;
temp->power = 0;
}
if (length == 0) {
C->next = temp;
}
else {
temp2->next = temp;
}
temp2 = temp;
length++;
}
C->length = A->length;
combiningLikeTerms(C);
return OK;
}
//求值運算
double evaluation(struct PolynomialHead* A, double value){
int i;
double result = 0;
struct Polynomial* numA = A->next;
for (i = 0; i < A->length; i++, numA = numA->next) {
result = result + numA->number * pow(value, (double)numA->power);
}
return result;
}
//把numA和numB全部存進numC
int mySave(struct PolynomialHead* A, struct PolynomialHead* B, struct PolynomialHead* C, int flag) {
int count = 0, i;
struct Polynomial *temp, *temp2;
struct Polynomial *numA = A->next, *numB = B->next;
for (i = 0; i < A->length || i < B->length; i++) {
if (numA->number != 0 && i < A->length) {
temp = (struct Polynomial*)malloc(sizeof(struct Polynomial));
temp->number = numA->number;
temp->power = numA->power;
numA = numA->next;
if (count == 0) {
C->next = temp;
}
else {
temp2->next = temp;
}
temp2 = temp;
count++;
}
if (numB->number != 0 && i < B->length) {
temp = (struct Polynomial*)malloc(sizeof(struct Polynomial));
temp->number = flag * numB->number;
temp->power = numB->power;
numB = numB->next;
if (count == 0) {
C->next = temp;
}
else {
temp2->next = temp;
}
temp2 = temp;
count++;
}
}
C->length = count;
return OK;
}
//在additionORsubtraction函數中,可能導致多項式長度不正確
int checkPolynomialLength(struct PolynomialHead* C) {
int i;
struct Polynomial* num = C->next;
int length = 0;
for (i = 0; i < C->length; i++, num = num->next) {
if (num->number != 0){
length++;
}
}
C->length = length;
return OK;
}
//排序
int myBubbleSort(struct PolynomialHead* C){
struct Polynomial *numi, *numj;
int i, j;
double temp;
for (i = 0, numi = C->next; i < C->length - 1; i++, numi = numi->next) {
for (j = i + 1, numj = numi->next; j < C->length; j++, numj = numj->next) {
if (numi->power > numj->power) {
if (numi->number == 0 || numj->number == 0) {
continue;
}
temp = numi->number;
numi->number = numj->number;
numj->number = temp;
temp = numi->power;
numi->power = numj->power;
numj->power = temp;
}
else if (numi->power == numj->power) {
if (numi->number == 0 || numj->number == 0) {
continue;
}
if (numi->number > numj->number) {
temp = numi->number;
numi->number = numj->number;
numj->number = temp;
}
}
}
}
return OK;
}
//顯示多項式
int showPolynomial(char ch, struct PolynomialHead* num, int operation) {
myBubbleSort(num);
switch (ch)
{
case 'C':
switch (operation)
{
case 1:
printf("加法的");
break;
case 2:
printf("減法的");
break;
case 3:
printf("乘法的");
break;
case 4:
printf("求導的");
break;
case 5:
printf("求值的");
break;
default:
break;
}
printf("計算結果為:");
printPolynomial('C', num);
break;
default:
printf("多項式%c 的內容為:", ch);
printPolynomial(ch, num);
break;
}
return OK;
}
//輸出多項式內容
int printPolynomial(char ch, struct PolynomialHead* C) {
int i;
struct Polynomial* num = C->next;
int flag1 = 0, flag2 = 0;
for (i = 0; i < C->length; i++, num = num->next){
if (num->number > 0 && i != 0 && flag2 == 1) {
printf("+");
flag1++;
}
if (num->number != 0 && num->power != 0) {
printf("%gx^%d", num->number, num->power);
flag1++;
flag2 = 1;
}
else if(num->number != 0 && num->power == 0) {
printf("%g", num->number);
flag1++;
}
}
if (flag1 == 0){
printf("0");
}
if (ch == 'A' || ch == 'B') {
printf("\n");
}
return OK;
}
5.實驗結果測試與分析
(1)數據測試程序截圖
(2)對結果進行分析:
①能正確合並同類項
②能正確的排序並輸出結果
③能正確處理常數項
④能正確處理指數為0的項已經系數為0的項
⑤能正確求值
6.思考及學習心得
(1)描述實驗過程中對此部分知識的認識:
(2)特別描述在學習方法上的收獲及體會;
(3)針對前面的思考題內容在此回答。
1)實踐了使用線性表對數據進行處理,更進一步掌握數組法與鏈表法的使用與轉換。
在設計程序時,上層設計一定要事先想好,否則到后面需要修改上層設計的時候,下層實現基本是需要全部推倒重做。
2)這次的實驗,鞏固了我的編程模塊化的思想。模塊化降低了程序的耦合性,提高了程序的內聚性;降低了程序復雜度,使程序設計、調試和維護等操作簡單化。模塊化使得程序設計更加簡單和直觀,從而提高了程序的易讀性和可維護性,而且還可以把程序中經常用到的一些計算或操作編寫成通用函數,以供隨時調用。
其次,深刻體會到做一個程序或者項目,老老實實去寫去設計,遠比空想來的快和實在。剛開始做的時候可能會比較迷茫,目標沒那么清晰,隨着程序的完成度越高,目標就越來越清晰。
3)我是先完成了數組法,隨后改寫成鏈表法的,實踐證明,如果程序的耦合性較低,數組法和鏈表法相互轉換的難度也比較低。再次說明了編程模塊化的重要性。若不以模塊化思想去編程,將會重寫、改寫很多不必要的代碼,毋庸置疑的是,模塊化更省時省力。