您的当前位置:首页正文

数据结构大作业

来源:九壹网


《数据结构与算法应用》

上机大作业

学院:电子工程学院 专业:遥感科学与技术

班级:1702071

组员:

选题:第一题、第二题、第六题

1 / 35

目录

第一题………………………………………………………………………………P3 第二题………………………………………………………………………………P13 第六题………………………………………………………………………………P22 实验心得体会………………………………………………………………………P34 详细分工及成绩申报………………………………………………………………P35

2 / 35

第一题

一.题目

利用带头结点的单链表实现两个集合的并、交、差运算。(难易程度:低)

二.题目功能描述

1、要求用带头结点的单链表存储两个集合中的元素和最终的结果。

2、集合的元素限定为十进制数,程序应对出现重复的数据进行过滤,即使得链 表中没有重复数据。

3、显示两个集合的内容及其并集、交集和差集的内容。

4、要求不改变原来的集合,并集、交集和差集分别另外存放。

三.概要设计

建立单链表过滤数据求集合的交,并,差集

四.程序源代码及相应的流程图

1.程序源代码

#include #include #include #include using namespace std; typedef char datatype; typedef struct LNode {

datatype data;

struct LNode *next; } LinkList;

void DispList(LinkList*L) {

LinkList *p=L->next; while(p!=NULL)

3 / 35

{

printf(\"%d \ p=p->next; }

printf(\"\\n\"); }

void DestroyList(LinkList *&L) {

LinkList*p=L->next,*pre=L; while(p!=NULL) {

free(pre); pre=p;

p=pre->next; }

free(pre); }

LinkList*CreateListF()//尾插法建立单链表 { LinkList*head,*p,*r,*s; datatype CreateListF_num; int n; printf(\"创立一个链表,大小为:\"); scanf(\"%d\ head=(LinkList*)malloc(sizeof(LinkList)); head->next=NULL; r=head; printf(\"输入以空格隔开的十进制整数:\"); for(int i=1,k=1;i<=n;i++,k++) { int flag=1; s=head->next; scanf(\"%d\ for(int j=1;jnext) { if(CreateListF_num==s->data) { flag=0; k--; break; } } if(flag) {

4 / 35

p=(LinkList*)malloc(sizeof(LinkList)); p->data=CreateListF_num; r->next=p; r=p; } } r->next=NULL; return head; }

///从小到大排序 void sort(LinkList *L) {

LinkList *pre,*p,*q; if(L->next!=NULL) { p=L->next->next; L->next->next=NULL; while(p!=NULL) { q=p->next; pre=L; while(pre->next!=NULL&&pre->next->datadata) pre=pre->next; p->next=pre->next; pre->next=p; p=q; } } }

void Delete(LinkList *head) { if(head->next!=NULL) { LinkList *p=head->next,*r=head,*q; while(p->next) { if(p->data==p->next->data) { q=p->next; p->next=q->next; free(q); }

5 / 35

else p=p->next; } } }

///求集合的并

void Union(LinkList *ha,LinkList*hb,LinkList*&hc) {

LinkList *pa=ha->next,*pb=hb->next,*pc,*s; hc=(LinkList*)malloc(sizeof(LinkList)); pc=hc;

while(pa!=NULL &&pb!=NULL ) {

if(pa->datadata) {

s=(LinkList*)malloc(sizeof(LinkList)); s->data=pa->data; pc->next=s; pc=s;

pa=pa->next; }

else if(pa->data>pb->data) {

s=(LinkList*)malloc(sizeof(LinkList)); s->data=pb->data; pc->next=s; pc=s;

pb=pb->next; } else {

s=(LinkList*)malloc(sizeof(LinkList)); s->data=pa->data; pc->next=s; pc=s;

pa=pa->next; pb=pb->next; } }

if(pb!=NULL) pa=pb; while(pa!=NULL) {

6 / 35

s=(LinkList*)malloc(sizeof(LinkList)); s->data=pa->data; pc->next=s; pc=s;

pa=pa->next; }

pc->next=NULL; }

///求两个有序集合的交用尾插法

void InterSect(LinkList *ha,LinkList*hb,LinkList*&hc) {

LinkList *pa=ha->next,*pb,*pc,*s; hc=(LinkList*)malloc(sizeof(LinkList)); pc=hc;

while(pa!=NULL) {

pb=hb->next;

while(pb!=NULL&&pb->datadata) pb=pb->next;

if(pb!=NULL &&pb->data==pa->data)///B节点在A节点中复制A节点 {

s=(LinkList*)malloc(sizeof(LinkList)); s->data=pa->data; pc->next=s; pc=s; }

pa=pa->next; }

pc->next=NULL; }

///求两个有序集合的差

void Subs(LinkList *ha,LinkList*hb,LinkList*&hc) {

LinkList *pa=ha->next,*pb,*pc,*s; hc=(LinkList*)malloc(sizeof(LinkList)); pc=hc;

while(pa!=NULL) {

pb=hb->next;

while(pb!=NULL&&pb->datadata) pb=pb->next;

if(!(pb!=NULL &&pb->data==pa->data))///B节点不在A节点中复制A节点 {

s=(LinkList*)malloc(sizeof(LinkList));

7 / 35

s->data=pa->data; pc->next=s; pc=s; }

pa=pa->next; }

pc->next=NULL; }

int main() {

LinkList *ha,*hb,*hc; ha=CreateListF(); hb=CreateListF();

printf(\" 集合的运算如下:\\n\"); printf(\" 原集合A: \"); DispList(ha);

printf(\" 原集合B: \"); DispList(hb); sort(ha); sort(hb); Delete(ha); Delete(hb); printf(\" 有序集合A: \"); DispList(ha); printf(\" 有序集合A: \"); DispList(ha);

Union(ha,hb,hc);

printf(\" 集合的并C: \"); DispList(hc);

InterSect(ha,hb,hc); printf(\" 集合的交C: \"); DispList(hc); Subs(ha,hb,hc);

printf(\" 集合的差C: \"); DispList(hc); DestroyList(ha); DestroyList(hb); DestroyList(hc); return 0; }

8 / 35

2.流程图

开始 输入数据 尾插法建立单链表 将输入数据从小到大排序 删除表中重复数据 求集合的交集 求集合的并集 求集合的差集 结束 9 / 35

五.程序运行结果

[测试数据]

1、set1={3, 8, 5, 8,11},set2={22, 6, 8, 3, 15,11,20 } set1∪set2= set1∩set2= set1-set2=

2、其中一个集合为空集 3、两个集合都是空集

4、创建集合时有重复数据的情况

测试1

测试2

10 / 35

测试3

测试4

集合元素用尾插法建立的单链表进行存储,原集合进行排序并删除重复元素后进行集合的相关运算。

六. 所采用存储结构的优缺点及理由

优点:

1.长度不固定,可以任意增删。

2.存储空间不连续,数据元素之间使用指针相连,每个数据元素只能访问周围的一个元素(根据单链表还是双链表有所不同)。 3.存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针)。

4.在特定的数据元素之后插入或删除元素,不涉及到其他元素的移动,因此时间复杂度为 O(1)。

11 / 35

缺点:

要访问特定元素,只能从链表头开始,遍历到该元素,时间复杂度为 O(n)。 采取单链表的理由:

由于集合运算有大量的删除、插入元素的操作,且数组的长度较短,无需访问大量元素,无随机查找元素需求,时间复杂度较顺序表而言更加具有优势,综合考虑,相比顺序表,单链表更适合进行集合的交并差运算。

12 / 35

第二题

一.题目2(栈、串)

利用栈实现算术表达式的求值。假设表达式中含有一位整数,以及+、-、*、/、(、)。但不受此限制。

二.题目功能描述

(1).表达式以字符串形式输入,并以‘#’开始和结束(‘#’也作为算法来处理)。 如输入:#6+3*(9-7)-8/2#

(2).能够有效判别表达式的输入格式是否有误(如缺失操作数、非法算符、括 号不匹配等错误),若输入格式错误,输出错误提示。 [测试数据]

1、#6+3*(9-7)-8/2# 2、#(8-2)/(3-1)*(9-6)# 3、#5+a*(8-4)/2# 4、#5+(7-3)*6#

三.概要设计

输入表达式

判断表达式是否有误

输出结果

四.程序的源代码、注释以及流程图

1.源代码和注释 #include #include

typedef struct { char data[50]; int top;

}stack;//顺序栈类型定义

void newstack(stack *&S)//初始化顺序栈 { S=(stack*)malloc(sizeof(stack)); S->top=-1; }

13 / 35

int push(stack*S,char e)//进栈 { if(S->top>49) { printf(\"in error!\\n\"); return 0; } else { S->data[++S->top]=e; return 1; } }

int empty(stack*S)//判断栈空 { if(S->top<0) return 1; else return 0; }

char pop(stack*S)//出栈 { char e; if(empty(S)) { printf(\"out error!\\n\"); return 0; } else { e=S->data[S->top--]; return e; } }

int isnum(char e)//判断是否为数字 { if(e>='0'&&e<='9') return 1; else return 0; }

int num(char e)//字符型转换为整型{ int n;

14 / 35

n=e-48;//ASCII码 return n; }

char nonum(int n)//整型转换为字符型 { char e; e=n+48;//ASCII码 return e; }

int correct(char s[])//判断括号是否匹配 { stack *S; newstack(S); int flag=1,i=1; while(s[i]!='#'&&flag) { if(s[i]=='(') push(S,s[i]); if(s[i]==')') if(pop(S)!='(') flag=0; i++; }//最先遇到的后括号前必定是与之对应的前括号,如若匹配不成功,则flag记为0,即括号不匹配 if(!empty(S)) flag=0; return flag; }

int rank(char a,char b)//判断运算符优先级,不包括括号的优先级 { if((a=='*'||a=='/')&&(b=='+'||b=='-')) return 1; else

return 0; }

void trans(char s1[],char s2[])//中缀表达式转换为后缀表达式,s1为中缀表达式,s2为后缀表达式 { int i=1,j=0; char e; stack *S; newstack(S); while(s1[i]!='#')

15 / 35

{ if(isnum(s1[i]))//是数字直接输出 s2[j++]=s1[i]; else//运算符号,括号的处理 { if(s1[i]=='(')//前括号直接入栈 push(S,s1[i]); if(s1[i]==')')//遇到后括号输出栈顶运算符直至遇到左括号,左括号出栈但不输出 while((e=pop(S))!='(') s2[j++]=e; if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/')//栈空入栈,栈顶为左括号入栈,优先级高于栈顶运算符入栈,否则出栈并再次判断,实际实现时先进行是否出栈判断 { while(!(empty(S)||S->data[S->top]=='('||rank(s1[i],S->data[S->top]))) s2[j++]=pop(S); if((empty(S)||S->data[S->top]=='('||rank(s1[i],S->data[S->top]))) push(S,s1[i]); } if(!(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/'||s1[i]=='('||s1[i]==')')) printf(\"非法运算符!\\n\"); //除过四则运算和括号(+、-、*、/、(、))外,其余判定为非法运算符 } i++; } while(!empty(S))//表达式读毕将栈内运算符一一输出 s2[j++]=pop(S); s2[j]='\\0';//字符串结尾 }

int workout(char s2[])//计算后缀表达式的值 { int a,b,i=0; stack *S; newstack(S); while(s2[i]!='\\0') { if(isnum(s2[i]))//数字入栈等待运算符操作 push(S,s2[i++]); else { b=num(pop(S));

16 / 35

a=num(pop(S));//字符型转为整型进行运算 switch(s2[i++]) { case'+': a=a+b; push(S,nonum(a)); break; case'-': a=a-b; push(S,nonum(a)); break; case'*': a=a*b; push(S,nonum(a)); break; case'/': a=a/b; push(S,nonum(a)); break;//运算后转为字符型入栈 default: printf(\"error!\"); } } } if(S->top!=0)//缺少运算符时,输出提示,但仍然带回栈顶元素的值作为运算结果输出 { printf(\"缺少运算符!得到中间结果!\\n\"); } a=num(pop(S));//字符型转为整形带入返回值 return a; }

int main() { int ans; char s1[80],s2[80]; printf(\"输入表达式:\"); gets(s1); if(!(correct(s1))) { printf(\"括号不匹配!\"); return 0; } else { trans(s1,s2); printf(\"后缀表达式:\"); puts(s2); ans=workout(s2); printf(\"ans=%d\\n\ system(\"pause\"); return 0; } }

2.流程图

17 / 35

开始 实现顺序栈的基本运算 输入表达式 是 是否为数字 否 直接输出 判断括号是否匹配 否 是 不匹配,则flag=0 判断符号优先级 18 / 35

判断非法运算符 输出栈内运算符 计算后缀表达式的值 结束 19 / 35

5.数据输入输出

20 / 35

此题运用了栈这种结构来解决问题,数据以字符串形式输入,栈是一种后进先出的线性表,方便进行比对,对有效判别表达式的输入格式是否有误有很大帮助,输入数据有序进行计算,是这个存储结构很大的优势。 6.栈的优缺点:

优点:连续存储,空间利用率高 缺点:不方便数据的增删

采用顺序栈更方便进行比对,对有效判别表达式的输入格式是否有误有很大帮助,输入数据有序进行计算,连续存储,空间利用率高。

21 / 35

第六题

一. 题目6(哈夫曼树的编/译码器)

[问题描述]

利用哈夫曼编码进行通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统将待传数据进行预先编码;在接受端将传来的数据进行解码(复原)。对于可以双向传输的信道,每端都要有一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼的编译码系统。(难易程度:高) [实验目的]

1、通过哈夫曼树的定义,掌握构造哈夫曼树的意义。 2、掌握构造哈夫曼树的算法思想。

3、通过具体构造哈夫曼树,进一步理解构造哈夫曼树编码的意义。 [实验内容及要求]

1、从终端读入字符集大小为n(即字符的个数),逐一输n个字符和相应的n个权值(即字符出现的频度),建立哈夫曼树,将它存于文件hfmtree中。并将建立好的哈夫曼树以树或凹入法形式输出;对每个字符进行编码并且输出。

2、利用已建好的哈夫曼编码文件hfmtree,对对已编码的正文进行译码,输出译码后的正文。

3、采用文本文件存放文本,先统计文本中的每个字符出现的频率,然后再建立哈夫曼树,并进行编码和译码。 [测试数据]

1、用下表给出的字符集和频度的实际统计数据建立哈夫曼树。 M N 字符 A B C D E F G H I J K L 频度 64 13 22 32 103 21 15 47 57 1 5 32 20 57 字符 O P Q R S T U V W X Y Z 空格 频度 63 15 1 48 51 80 23 8 18 1 16 1 168 并实现以下报文的译码和输出:THISPROGRAMISMYFAVORITE 2、采用文本文件存放文本,测试实验内容及要求的第3项。

二. 题目功能描述

利用哈夫曼编码进行通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统将待传数据进行预先编码;在接受端将传来的数据进行解码(复原)。对于可以双向传输的信道,每端都要有一个完整的编/译码系统。

三. 概要设计图

22 / 35

输出解码

输入频率统计词频读取文件

压缩

转码压缩查找位置

选择两个最小下标

构造哈夫曼树

四. 源代码及相应的流程图

1.程序源代码: #include #include #include #include #include

using namespace std;

//只考虑字母加空格 const int max_size = 27;

struct element {

char data;// 保存的符号 int weight;// 权值

int lchild,rchild,parent;// 左孩子,右孩子,根结点 int count; //子节点个数 };

class HuffmanTree {

private:

// 字符总数 int num;

// 保存各个叶子的权值,即字符出现的个数频率 int w[max_size]; // 编码结果

map code_result; // 树结构

element huffTree[2*max_size-1]; // 判断位置

int indexOf(char ch); // 选择最小值

void Select(int &i1, int &i2); // 读取文件

23 / 35

string read_file(); // 保存压缩文件

void save_code(int code_cache[], int code_cache_size); // 统计文本中出现的字母和频率 void CountLetter(string& str);

// 输入字母和频率,由于空格输入的问题,不支持同时输入字符和频率. void InputLetter(); // 打印输出

void print(element e); // 转码压缩

void condense(string str); // 解码

void decoding();

public:

// 构造函数 HuffmanTree() ; };

//输出

void HuffmanTree::print(element e) { cout << e.weight << \"\\"; for(int i = 0 ; i < e.count; i++) cout << e.data; cout << endl; if(e.lchild != -1)

print(huffTree[e.lchild]); if(e.rchild != -1)

print(huffTree[e.rchild]); }

//解码

void HuffmanTree::decoding() { string str;

ifstream in(\"hfmtree.txt\ in>>str; in.close();

ofstream out(\"output.txt\ int root = 2*num-2; int temp = root; string code;

for (int i = 0;i < str.size(); i++) { code += str.at(i); if (str.at(i) == '0') {

if (huffTree[temp].lchild != -1) {

24 / 35

temp = huffTree[temp].lchild; if (huffTree[temp].lchild == -1) { out<code_result[huffTree[temp].data] = code; code.clear(); temp = root; } } } else {

if (huffTree[temp].rchild != -1) { temp = huffTree[temp].rchild; if (huffTree[temp].rchild == -1) { out<code_result[huffTree[temp].data] = code; code.clear(); temp = root; } } } }

out.close();

map::iterator iter;//定义一个迭代指针iter cout << \"编码结果为 :\" << endl;

for(iter=code_result.begin(); iter!=code_result.end(); iter++) {

cout << iter->first<<\" \"<second<//输入频率

void HuffmanTree::InputLetter() {

int size = 27; char ch[size]; int weight[size]; num = 0;

cout << \"依次输入27个字母出现的频率,不出现输入0:\\n\";

//64 13 22 32 103 21 15 47 57 1 5 32 20 57 63 15 1 48 51 80 23 8 18 1 16 1 168 for(int i = 0 ; i < size; i++) { cin >> weight[i]; ch[i] = 'A' + i; }

ch[26] = ' ';

25 / 35

for (int i = 0;i < size; i++) { if (weight[i] != 0) {

huffTree[num].data = ch[i];

huffTree[num].weight = weight[i]; w[num] = weight[i]; num++; } } }

//统计词频

void HuffmanTree::CountLetter(string& str) { int size = 27; char ch[size]; int weight[size]; num = 0; ch[0] = 'A'; ch[26] = ' ';

for (int i = 1;i < size - 2; i++) { ch[i] = ch[i-1] + 1; }

for (int i = 0;i < size; i++) { weight[i] = 0; }

for (int i = 0;i < str.size(); i++) {

if (str.at(i) > 64 && str.at(i) < 91) { weight[str.at(i) - 'A']++; }

if (str.at(i) == ' ') { weight[26]++; } }

cout << \"统计结果为:\" << endl; for (int i = 0;i < size; i++) { if (weight[i] != 0) {

huffTree[num].data = ch[i];

huffTree[num].weight = weight[i]; w[num] = weight[i]; num++;

// cout << ch[i] << ' ' << weight[i] <26 / 35

//读取文件

string HuffmanTree::read_file() { string str;

ifstream in(\"123.txt\ char ch;

in >> noskipws; //确保能读入空格 while(in >> ch) { str += ch; }

in.close();

// cout <//压缩

void HuffmanTree::save_code(int code_cache[], int code_cache_size) { ofstream out(\"hfmtree.txt\ for (int i = 0;i < code_cache_size; i++) { out<out.close(); }

//转码压缩

void HuffmanTree::condense(string str) { // 缓存转码数据数组的最大缓存大小 int code_cache_max_size = 256; // temp stack s;

// 缓存转码数据数组

int code_cache[code_cache_max_size]; // 缓存游标

int code_cache_index = 0; // 判断是左子树还是右子树 int Judge_Direction; // 是否上溢

bool isOverflow = false;

for (int i = 0; i < str.size(); i++) { int index = indexOf(str.at(i));

Judge_Direction = huffTree[index].parent; while (Judge_Direction != -1) {

if (index == huffTree[Judge_Direction].lchild) {

27 / 35

s.push(0); } else {

s.push(1); }

index = Judge_Direction;

Judge_Direction = huffTree[Judge_Direction].parent; }

while (!s.empty()) {

code_cache[code_cache_index++] = s.top(); s.pop(); }

if (code_cache_index % code_cache_max_size == code_cache_max_size - 1) {

save_code(code_cache, code_cache_max_size); code_cache_index = 0; isOverflow = true; } }

if (!isOverflow) {

save_code(code_cache, code_cache_index); } }

//查找位置

int HuffmanTree::indexOf(char ch) { for (int i = 0;i < num; i++) {

if (huffTree[i].data == ch) { return i; } }

return -1; }

//选择两个最小下标

void HuffmanTree::Select(int &i1, int &i2) { int i;

bool button = true;

for (i = 0;i < 2*num-1; i++) { if (button) {

if (huffTree[i].parent == -1) { i1 = i;

button = false; } } else {

28 / 35

if (huffTree[i].parent == -1) { i2 = i; break; } }

}

for (i = 0;i < 2*num-1; i++) {

if (i2 != i && huffTree[i].parent == -1 && huffTree[i].weight > 0) { if (huffTree[i1].weight > huffTree[i].weight) { i1 = i; } } }

for (i = 0;i < 2*num-1; i++) {

if (i1 != i && huffTree[i].parent == -1 && huffTree[i].weight > 0) { if (huffTree[i2].weight > huffTree[i].weight) { i2 = i; } } } }

//构造

HuffmanTree::HuffmanTree() { string str = read_file(); // CountLetter(str); InputLetter();

for (int i = 0;i < 2*num-1;i++) { huffTree[i].parent = -1; huffTree[i].lchild = -1; huffTree[i].rchild = -1; huffTree[i].count = 1; }

for (int i = 0;i < 2*num - 1; i++) { if (i < num) {

huffTree[i].weight = w[i];// 构造2*n-1棵只含有根节点的二叉树 } else {

huffTree[i].weight = 0; } }

for (int k = num;k < 2*num-1; k++) { int i1,i2;

Select(i1, i2);

29 / 35

huffTree[i1].parent = k; huffTree[i2].parent = k;

huffTree[k].weight = huffTree[i1].weight + huffTree[i2].weight; huffTree[k].lchild = i1; huffTree[k].rchild = i2;

huffTree[k].count = huffTree[i1].count + huffTree[i2].count; huffTree[k].data = '*'; }

print(huffTree[2*num-2]);

cout<<\"------------------------\"<int main() {

new HuffmanTree(); return 0; }

2.流程图:

开始 输入/读取文件 构建哈夫曼树 统计词频、编码、解码…… 结束

30 / 35

五. 程序运行结果

统计词频结果

编码结果

树结果

31 / 35

输入文本内容

编码结果

32 / 35

解码结果

六. 所采用存储结构的优缺点及理由

程序运用了孩子双亲表示法。题中有两个要求:一种是要从终端读入字符集大小为n(即字符的个数),逐一输入n个字符和相应的n个权值(即字符出现的频度),建立哈夫曼树,将它存于文件hfmtree中,并将建立好的哈夫曼树以树或凹入法形式输出;对每个字符进行编码并且输出,利用已建好的哈夫曼编码文件hfmtree,对已编码的正文进行译码,输出译码后的正文。另一种是需要采用文本文件存放文本,先统计文本中的每个字符出现的频率,然后再建立哈夫曼树,并进行编码和译码。从终端输入数据时需要注释第283行,从文件读取时注释第284行,取消注释283行即可。

双亲孩子表示法具有双亲表示法和孩子表示法两种存储结构优点,便于对孩子和双亲进行操作,但操作实现比较麻烦。

33 / 35

实验心得体会

本次上机实验,使我们对《数据结构》这门课程有了更深入的理解。《数据结构》是一门实践性较强的课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践。

通过这次作业,我们深刻了解了单链表、顺序栈、树等等在实际应用中的作用,学会了运用各种数据结构解决问题,但在有的细节方面依然存在着疑惑。我们在掌握了理论基础后通过编写代码解决问题增强了实践能力,对相关理论也有了更深入的理解。在以后相关内容的学习中,我们也会增强上机实践,提高动手能力,将学到的知识转化为自己解决问题的工具,在不断的尝试、失败、修改中提高自己。

通过这段时间的学习,我们认识到数据结构是一门比较难的课程,需要多花时间上机练习。上机实验培养了我们实际分析问题、编程和动手能力,使我们掌握了程序设计的基本技能,提高了适应实际和实践编程的能力。

总的来说,这次课程设计让我们获益匪浅,对数据结构也有了进一步的理解和认识。

34 / 35

详细分工及成绩申报

组员 学号 具体任务 完成情况 成绩申报 85 第六题 完成 85 第一题 完成 85 第二题 完成

35 / 35

因篇幅问题不能全部显示,请点此查看更多更全内容

Top