魔装少男的博客

我可爱又美丽却能唤来死亡
虽然我可爱又迷人,但我能招来死亡

数据结构第一次实验报告

实验1 线性表的实现与应用

实验目的

  1. 掌握顺序表的实现及基本操作
  2. 掌握单链表的实现及基本操作
  3. 编写主函数,调用操作函数解决应用问题
  4. 增加代码经验,加深对C语言的理解

二.实验内容

1项目2_1:顺序表实现一般集合求并集。

【问题描述】

有集合A={7,5,3,11}和集合B={2,6,3},现需要将他们合并

【算法分析】

在原有可动态分配大小的顺序表上进行修改首先调用建表函数AB放入两张表里然后调用合并函数

在合并函数里先用if保证被插入的永远为长的表再用一个for不停用getElemByIndex取短表里的元素再用getIndexByElem获取该元素在长表里的位置如果返回为-1则调用ListInsert插入

2. 项目2_2:单链表实现有序集合求并集。

【问题描述】

现有有序集合A={3,5,8}B={2,6,8,9,11,15,20},现需将他们合并为有序集合。

【算法分析】

在单链表的基础上进行更改。首先调用尾插法建表函数AB放入两张表里,然后调用合并函数。

在合并函数里,先用if保证被插入的永远为长的表,再用两个for进行逻辑处理。第一个for不停getListByIndex从短链表取元素前一个结点,进行下一步逻辑。第二个for不停用getListByIndex长表取元素的前一个结点并比较下一个结点的值与第一个for里取出的结点的下一个结点的值,然后调用insertList插入

3.项目2-3:单链表实现一元稀疏多项式加法运算。

【问题描述】

现有多项式,需要进行合并成一个多项式。

【算法分析】

通过分析发现与上一个项目的代码有相似之处,更改结构定义和各个函数。由于和上一个项目相似,所以分析关键代码。

先将指数相同项的系数相加,后将没有的项插入(虽看起来简单,其实比较难的。我还添加一个可以带入x计算结果功能)。

 

源代码

1. 一般集合的并集2_1_彭喜.cpp


  1. #include<stdio.h>  
  2. #include<iostream>  
  3. #include<malloc.h>  
  4. #include<stdlib.h>  
  5. using namespace std;  
  6. #define OK 1 //通过  
  7. #define ERROR 0 //错误   
  8. #define OVERFLOW -2 //堆栈溢出  
  9. #define LIST_INIT_SIZE 10 //线性表储存空间初始分配量  
  10. #define LISTINCREMRNT 10 //线性表储存空间的分配增量  
  11. typedef int Status; //函数类型,其值为状态码  
  12. typedef int ElemType; //抽象数据类型  
  13.                       //线性表动态分配顺序储存结构  
  14. typedef struct  
  15. {  
  16.     ElemType* elem;//储存空间基址  
  17.     int length;//当前长度  
  18.     int listsize;//当前分配的存储容量  
  19. }SqList;  
  20.   
  21. //初始化一个空的表  
  22. Status InitList(SqList* L)  
  23. {  
  24.   
  25.     L->elem = (ElemType*)__vcrt_malloc_normal(LIST_INIT_SIZE * sizeof(ElemType));  
  26.     if (!(L->elem))  
  27.         exit(OVERFLOW);//分配失败  
  28.     L->length = 0;//长度  
  29.     L->listsize = LIST_INIT_SIZE;//容量  
  30.   
  31.     return OK;  
  32. }  
  33.   
  34. //插入  
  35. Status ListInsert(SqList* L, int i, ElemType e)  
  36. {  
  37.     if (i<1 || i>L->length + 1)  
  38.         return ERROR;  
  39.   
  40.     ElemType* q = &(L->elem[i - 1]), *p = NULL;// q为插入位置  
  41.     for (p = &(L->elem[L->length - 1]); p >= q; --p)  
  42.         * (p + 1) = *p;// 插入位置及之后的元素后移  
  43.     *q = e;// 插入e  
  44.     ++(L->length);// 表长增加1  
  45.     if (L->length == L->listsize) {  
  46.         ElemType*  newbase = (ElemType*)realloc(L->elem, (L->listsize + LISTINCREMRNT) * sizeof(ElemType));  
  47.         if (!newbase)  
  48.             exit(OVERFLOW);  
  49.         L->elem = newbase;// 新基址  
  50.         L->listsize += LISTINCREMRNT;// 增加存储容量  
  51.     }  
  52.     return OK;  
  53. }  
  54. //获取长度  
  55. int getLength(SqList* L)  
  56. {  
  57.     return L->length;  
  58. }  
  59. //通过索引取值  
  60. ElemType getElemByIndex(SqList* L, int i)  
  61. {  
  62.     return L->elem[i - 1];  
  63. }  
  64. //通过值取索引  
  65. int getIndexByElem(SqList* L, ElemType e)  
  66. {  
  67.     for (int j = 0; j < L->length; ++j)  
  68.     {  
  69.         if ((L->elem[j]) == e)  
  70.             return j + 1;  
  71.     }  
  72.     return -1;  
  73. }  
  74.   
  75. //遍历表  
  76. Status myPrintf(SqList* L)  
  77. {  
  78.     for (int i = 0; i < L->length; i++) {  
  79.         cout << ""<< i + 1<<"------------" << (L->elem[i])<<endl;  
  80.           
  81.     }  
  82.     return OK;  
  83. }  
  84. //创建表  
  85. Status creatList(SqList* L)  
  86. {  
  87.     scanf_s("%d", &(L->length));  
  88.     printf("输入为 %d\n", L->length);  
  89.     for (int i = 0; i < L->length; i++)  
  90.     {  
  91.         cin >> L->elem[i];  
  92.   
  93.     }  
  94.     return OK;  
  95. }  
  96. //合并  
  97. Status mergeList(SqList* LA,SqList* LB)  
  98. {  
  99.     if (LA->length < LB->length) {  
  100.         SqList* temp;  
  101.         temp = LA;  
  102.         LA = LB;  
  103.         LB = temp;  
  104.     }  
  105.     for (int i = 0; i < LB->length; i++)  
  106.     {  
  107.         ElemType e = getElemByIndex(LB,i+1);  
  108.         if (getIndexByElem(LA, e)==-1) {  
  109.             ListInsert(LA, 1, e);  
  110.         }  
  111.     }  
  112.     printf("合并后\n");  
  113.     myPrintf(LA);  
  114.     return OK;  
  115. }  
  116. int main(void) {  
  117.     SqList* LA = (SqList*)__vcrt_malloc_normal(sizeof(SqList));  
  118.     InitList(LA);  
  119.     printf("请输入表A的长度\n");  
  120.     creatList(LA);  
  121.     myPrintf(LA);  
  122.     SqList* LB = (SqList*)__vcrt_malloc_normal(sizeof(SqList));  
  123.     InitList(LB);  
  124.     printf("请输入表B的长度\n");  
  125.     creatList(LB);  
  126.     myPrintf(LB);  
  127.   
  128.     mergeList(LA, LB);  
  129.     system("pause");  
  130.       
  131.     return 0;  
  132. }  


运行截图

 

 

 

 

 

 

 


 

 

 

2有序集合求并集2_2_彭喜.cpp


  1. #include<stdio.h>  
  2. #include<malloc.h>  
  3. #include<stdlib.h>  
  4. #define OK 1 //通过  
  5. #define ERROR 0 //错误   
  6. typedef int Status; //函数类型,其值为状态码  
  7. typedef int ElemType; //抽象数据类型  
  8.                        //单链表  
  9. typedef struct LNode  
  10. {  
  11.     ElemType data;  
  12.     struct LNode *next;  
  13. }LNode, *LinkList;  
  14. //初始化  
  15. Status initList(LinkList* L)  
  16. {  
  17.     *L = (LinkList)malloc(sizeof(LNode));  
  18.     (*L)->data = 0;  
  19.     (*L)->next = NULL;  
  20.     return OK;  
  21. }  
  22. //判空  
  23. char* isEmpty(LinkList* L)  
  24. {  
  25.     return (*L)->next == NULL ? "" : "不空";  
  26. }  
  27. //获取长度  
  28. int getLength(LinkList* L)  
  29. {  
  30.     LinkList p = *L;  
  31.     int i = 0;  
  32.     while (p->next)  
  33.     {  
  34.         ++i;  
  35.         p = p->next;  
  36.     }  
  37.     return i;  
  38. }  
  39. //默认头插法建表  
  40. Status creatListHead(LinkList* L , ElemType str[],int n)  
  41. {  
  42.     LinkList p;  
  43.     (*L)->data = n;  
  44.     for (int i = 0; i <n; ++i)  
  45.     {  
  46.         p = (LinkList)malloc(sizeof(LNode));  
  47.         p->data = str[i];  
  48.         p->next = (*L)->next;
  49.         (*L)->next = p;  
  50.     }  
  51.     return OK;  
  52. }  
  53. //默认尾插法建表   
  54. Status creatListEnd(LinkList* L, ElemType str[], int n)  
  55. {  
  56.     LinkList p, r = *L;  
  57.   
  58.     (*L)->data = n;  
  59.     for (int i = 0; i < n; ++i)  
  60.     {  
  61.         p = (LinkList)malloc(sizeof(LNode));  
  62.         p->data = str[i];  
  63.         p->next = NULL;//必须要否则遍历异常  
  64.         r->next = p;  
  65.         r = p;  
  66.     }  
  67.     return OK;  
  68. }  
  69. //遍历表  
  70. Status traversalList(LinkList L)  
  71. {  
  72.     LinkList p = L->next;  
  73.     while (p)  
  74.     {  
  75.         printf("%d ", p->data);  
  76.         p = p->next;  
  77.     }  
  78.     printf("\n");  
  79.     return OK;  
  80. }  
  81. //插入  
  82. Status insertList(LinkList* L, int i, ElemType c)  
  83. {  
  84.     if (L == NULL || (i > (*L)->data || i < 1))return ERROR;  
  85.     LinkList p = *L;  
  86.     int j = 0;  
  87.     while (p&&j<i - 1)  
  88.     {  
  89.         p = p->next;//定在前一个  
  90.         j++;  
  91.     }  
  92.     LinkList q = (LinkList)malloc(sizeof(LNode));  
  93.     q->data = c;  
  94.     q->next = p->next;  
  95.     p->next = q;  
  96.     (*L)->data++;  
  97.     return OK;  
  98. }  
  99. //按位查找  
  100. LNode* getListByIndex(LinkList L, int i)  
  101. {  
  102.     //if (L == NULL || (i > (L)->data || i < 1))return NULL;  
  103.     LinkList p = L;  
  104.     int j = 0;  
  105.     while (p&&j<i - 1)  
  106.     {  
  107.         p = p->next;//前一个  
  108.         j++;  
  109.     }  
  110.     //  p = p->next;  
  111.     return (p);//前一个  
  112. }  
  113. //按值查找  
  114. LNode* getListByElem(LinkList L, ElemType c,int* i)  
  115. {  
  116.     LinkList p = L;  
  117.     int j = 0;  
  118.     while (p&&p->next->data != c)  
  119.     {  
  120.         p = p->next;//前一个  
  121.         j++;  
  122.     }  
  123.     *i = j + 1;  
  124.     return p->next;   
  125. };  
  126. //合并  
  127. Status mergeList(LinkList* LA, LinkList* LB )  
  128. {  
  129.     if (getLength(LA)>getLength(LB))  
  130.     {  
  131.         LinkList* temp=LA;  
  132.         LA = LB;  
  133.         LB = temp;  
  134.     }  
  135.     ElemType e;  
  136.     for (int i = 1; i <= getLength(LA); i++)  
  137.     {  
  138.          e = getListByIndex(*LA, i)->next->data;//取元素  
  139.         //printf("___%d\n", e);  
  140.         for (int i = 1; i <= getLength(LB); i++)  
  141.         {  
  142.         //  printf("___---%d\n", i);  
  143.             if (getListByIndex(*LB, i)->next->data>e)  
  144.             {  
  145.                 //printf("_----__%d\n", i);  
  146.                 insertList(LB, i, e);  
  147.                 break;  
  148.             };  
  149.         }  
  150.     }  
  151.     printf("合并后: ");  
  152.     traversalList(*LB);  
  153.     return OK;  
  154. }  
  155.   
  156. int main(void)  
  157. {  
  158.     ElemType stra[4] = { 3,5,8,11 };  
  159.     ElemType strb[7] = { 2,6,8,9,11,15,20 };  
  160.     LinkList LA,LB;  
  161.     initList(&LA);  
  162.     initList(&LB);  
  163.     creatListEnd(&LA, stra,sizeof(stra)/sizeof(stra[0]));  
  164.     creatListEnd(&LB, strb, sizeof(strb) / sizeof(strb[0]));  
  165.     printf("LA: ");  
  166.     traversalList(LA);  
  167.     printf("LB: ");  
  168.     traversalList(LB);  
  169.     mergeList(&LA, &LB);  
  170.     system("pause");  
  171.     return 0;  
  172. }  

运行截图

 

 

 

 

 

3. 一元稀疏多项式加法2_3_彭喜.cpp


  1. #include<stdio.h>  
  2. #include<math.h>  
  3. #include<stdlib.h>  
  4. #define OK 1 //通过  
  5. #define ERROR 0 //错误   
  6. typedef int Status; //函数类型,其值为状态码  
  7. typedef long double ElemType; //抽象数据类型  
  8. //单链表  
  9. typedef struct LNode  
  10. {  
  11.     ElemType conf;//系数  
  12.     ElemType expn;//指数  
  13.     struct LNode *next;  
  14. }LNode, *LinkList;  
  15. //初始化  
  16. Status initList(LinkList* L)  
  17. {  
  18.     *L = (LinkList)malloc(sizeof(LNode));  
  19.     (*L)->conf = -1;  
  20.     (*L)->expn = -1;  
  21.     (*L)->next = NULL;  
  22.     return OK;  
  23. }  
  24. //判空  
  25. char* isEmpty(LinkList* L)  
  26. {  
  27.     return (*L)->next == NULL ? "" : "不空";  
  28. }  
  29. //获取长度  
  30. int getLength(LinkList* L)  
  31. {  
  32.     LinkList p = *L;  
  33.     int i = 0;  
  34.     while (p->next)  
  35.     {  
  36.         ++i;  
  37.         p = p->next;  
  38.     }  
  39.     return i;  
  40. }  
  41.   
  42. //默认尾插法建表   
  43. Status creatListEnd(LinkList* L, ElemType c[], ElemType e[], int n)  
  44. {  
  45.     LinkList p, r = *L;  
  46.     for (int i = 0; i < n; ++i)  
  47.     {  
  48.         p = (LinkList)malloc(sizeof(LNode));  
  49.         p->conf = c[i];  
  50.         p->expn = e[i];  
  51.         p->next = NULL;//必须要否则遍历异常  
  52.         r->next = p;  
  53.         r = p;  
  54.     }  
  55.     return OK;  
  56. }  
  57. //遍历表  
  58. Status traversalList(LinkList L)  
  59. {  
  60.     LinkList p = L->next;  
  61.     while (p)  
  62.     {  
  63.         if (p->conf>=0)  
  64.         {  
  65.             printf("+%fx^%f", p->conf,p->expn);  
  66.         }  
  67.         else  
  68.         {  
  69.             printf("%fx^%f", p->conf, p->expn);  
  70.         }  
  71.         p = p->next;  
  72.     }  
  73.     printf("\n");  
  74.     return OK;  
  75. }  
  76. //插入  
  77. Status insertList(LinkList* L, int i, ElemType c, ElemType e)  
  78. {  
  79.     if (L == NULL || (i > getLength(L) || i < 1))return ERROR;  
  80.     LinkList p = *L;  
  81.     int j = 0;  
  82.     while (p&&j<i - 1)  
  83.     {  
  84.         p = p->next;//定在前一个  
  85.         j++;  
  86.     }  
  87.     LinkList q = (LinkList)malloc(sizeof(LNode));  
  88.     q->conf = c;  
  89.     q->expn = e;  
  90.     q->next = p->next;  
  91.     p->next = q;  
  92.     return OK;  
  93. }  
  94. //按位查找  
  95. LNode* getListByIndex(LinkList L, int i)  
  96. {  
  97.     //if (L == NULL || (i > (L)->data || i < 1))return NULL;  
  98.     LinkList p = L;  
  99.     int j = 0;  
  100.     while (p&&j<i - 1)  
  101.     {  
  102.         p = p->next;//前一个  
  103.   
  104.         j++;  
  105.     }  
  106.     //  p = p->next;  
  107.     return (p);//前一个  
  108. }  
  109. //按值查找  
  110. LNode* getListByElem(LinkList L, ElemType e, int* i)  
  111. {  
  112.     LinkList p = L;  
  113.     int j = 0;  
  114.     while (p&&p->next->expn != e)  
  115.     {  
  116.         p = p->next;//前一个  
  117.         j++;  
  118.     }  
  119.     *i = j + 1;  
  120.     return p->next;  
  121. };  
  122. //计算  
  123. long double calculateMultinomial(LinkList L, int x)  
  124. {  
  125.     LinkList p = L->next;  
  126.     long double sum=0;  
  127.     while (p)  
  128.     {  
  129.         sum = p->conf*pow(x, p->expn)+sum;  
  130.         p = p->next;  
  131.     }  
  132.   
  133.     return sum;  
  134. }  
  135. //合并  
  136. Status mergeList(LinkList* LA, LinkList* LB)  
  137. {  
  138.     if (getLength(LA)>getLength(LB))  
  139.     {  
  140.         LinkList* temp = LA;  
  141.         LA = LB;  
  142.         LB = temp;  
  143.     }  
  144.     ElemType e,c;  
  145.     for (int i = 1; i <= getLength(LA); i++)  
  146.     {  
  147.         e = getListByIndex(*LA, i)->next->expn;//取指数  
  148.         c = getListByIndex(*LA, i)->next->conf;//取系数  
  149.         //先指数相同  
  150.         for (int i = 1; i <= getLength(LB); i++)  
  151.         {  
  152.             if (getListByIndex(*LB, i)->next->expn==e)  
  153.             {  
  154.                 getListByIndex(*LB, i)->next->conf =getListByIndex(*LB, i)->next->conf + c;//系数相加  
  155.                 break;  
  156.             };  
  157.         }  
  158.         //指数不同  
  159.         for (int i = 1; i <= getLength(LB); i++)  
  160.         {  
  161.             if (getListByIndex(*LB, i)->expn<e&&getListByIndex(*LB, i)->next->expn>e)  
  162.             {  
  163.                 insertList(LB, i, c, e);  
  164.                 break;  
  165.             };  
  166.         }  
  167.     }  
  168.     printf("多项式相加后: ");  
  169.     traversalList(*LB);  
  170.     printf("请输入x的值 ");  
  171.     int x;  
  172.     scanf_s("%d", &x);  
  173.     printf("答案为 %f\n\n", calculateMultinomial(*LB, x));  
  174.     return OK;  
  175. }  
  176. int main(void)  
  177. {  
  178.     ElemType ac[4] = { 7,3,9,5 };//系数  
  179.     ElemType ae[4] = { 0,1,8,17 };//指数  
  180.     ElemType bc[3] = { 8,22,-9};  
  181.     ElemType be[3] = { 1,7,8};  
  182.     LinkList LA, LB;  
  183.     int x;  
  184.     initList(&LA);  
  185.     initList(&LB);  
  186.     creatListEnd(&LA, ac,ae,4 );  
  187.     creatListEnd(&LB, bc, be, 3);  
  188.     printf("多项式LA: ");  
  189.     traversalList(LA);  
  190.     printf("请输入x的值 ");  
  191.     scanf_s("%d", &x);  
  192.     printf("答案为 %f\n\n", calculateMultinomial(LA, x));  
  193.     printf("多项式LB: ");  
  194.     traversalList(LB);  
  195.     printf("请输入x的值 ");  
  196.     scanf_s("%d", &x);  
  197.     printf("答案为 %f\n\n", calculateMultinomial(LB, x));  
  198.     mergeList(&LA, &LB);  
  199.     system("pause");  
  200.     return 0;  
  201. }  

运行截图

.问题总结

  1. 这次实验用的是vs2015编译器编写,增加了熟练度,还进一步加强了对调试的使用经验,加深了对指针、结构体和线性表的理解。
  2. 这次实验一不小心多写了一个有序集合使用顺序表合并,具体代码可见我的博客https://pengxiandyou.github.io  (GIthub上搭建的,速度较慢,耐心等待)
  3. 第一个项目比较简单,没什么需要百度的问题,写起来比较轻松。
  4. 第二个项目有点困难了,出来点小问题,例如野指针、插入位置不对等,不过这些都解决了。还有一个小问题,那就是和书上一样会把相同的也插入(第三个项目里解决了),不过我比书少用一张表。
  5. 第三个项目巧妙修改了定义使得在一个结点可以存放两个值,巧妙的修改了初始化让代码逻辑减少许多。先将指数相同的系数相加,在将没有的插入也是一个很棒的设计。添加一个计算功能更是锦上添花。小问题也就是像条件分析得有点久。
  6. 卡住的一个略大的问题是C语言中没有关于数组长度函数,所以一般用sizeof(a)/sizeof(int)来计算数组长度,但是当数组作参数传递时,函数里面sizeof(a)/sizeof(int)会等于1(应该或2)。这是因为编译器会将a当一个指针。
  7. 反正当出现问题时,调试是一个很棒的工具。