精华内容
下载资源
问答
  • 大学上数据结构课程自己写的数据结构实验,供参考 其中包括:学生管理系统(链表),算术表达式求值(栈和队列),KMPandBF算法,Huffman树和Huffman编码,完全二叉树的操作,学生管理系统plus(排序和查找)
  • 数据结构实验报告汇总共5篇。dos 谢谢 合作
  • 数据结构课程设计 停车场管理问题 姓名: 学号: 问题描述 设有一个可以停放n辆汽车的狭长停车场它只有一个大门可以供车辆进出车辆按到达停车场时间 的早晚依次从停车场最里面向大门口处停放最先到达的第一辆车放在...
  • 金陵科技学院实验报告 学 生 实 验 报 告 册 理工类 课程名称算法与数据结构 专业班级 _ 学生学号_ 所属院部 ------------ 学生姓名 _ 指导教师 20 13 20 14 学年 第 2 学期 金陵科技学院教务处制 金陵科技学院实验...
  • 大二计算机学生报告的汇总 进入计算机专业以来每天的必要工作就是写报告,...报告汇总之c语言数据结构报告篇(一) 学生信息管理系统 代码区 代码说明:此代码所运用的软件是ios系统的x-code #include <stdio.h...

    大二计算机学生报告的汇总

    进入计算机专业以来每天的必要工作就是写报告,按照老师的话来说,我们计算机专业的学生经过长时间的训练,以后出去写代码就跟喝水一样简单.在这里我将发表部分我写的报告,仅以此怀念我的大二时光.(报告写的不好.仅供欣赏)

    报告汇总之c语言数据结构报告篇(一)

    学生信息管理系统

    代码区

    代码说明:此代码所运用的软件是ios系统的x-code

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    int sum;
    //创建一个学生的信息结构体
    typedef struct student{
        long id;
        char name[64];
        float grade;
    }s;
    //定义顺序表
    typedef struct {
        s* student;
        int length;
    }SqList;
    //构造空顺序表
    int CreatStudent(SqList*L){
        L->student=(s*)malloc(sizeof(s));
        if (L->student==NULL)
            return 0;
        else
        {
            L->length=0;
            return 1;
        }
    }
    //录入基础学生信息和需要插入的学生信息
    void GetStudent(SqList*L,int i){
        printf("请输入学生的学号:");
        scanf("%ld",&L->student[i].id);
        printf("请输入学生的姓名:");
        scanf("%s",L->student[i].name);
        printf("请输入学生的成绩:");
        scanf("%f",&L->student[i].grade);
        L->length++;
    }
    void jiaohuan(SqList*L,int i);
    //打印学生信息
    void PrintStudent(SqList*L,int i)
    {
        printf("%ld\n%s\n%.3f\n\n",L->student[i].id,L->student[i].name,L->student[i].grade);
    }
    //查找指定的学生信息
    void FindStudent (SqList*L)
    {
        int n;
        printf("请输入查找方式:\n0=学号查找\n1=存储位置查找");//查找方式的选择
        scanf("%d",&n);
        printf("请输入需要查找学生的信息:");
        switch (n) {
            case 0:
            {
                long number;//输入需要查找的学生学号
                scanf("%ld",&number);
                for (int i=0;i<=L->length;i++)
                {
                    if (number==L->student[i].id)
                        PrintStudent(L,i);//打印出查找到的学神信息
                }
                break;
            }
            case 1:
            {
                int number;
                scanf("%d",&number);//输入需要查找的学生位置
                PrintStudent(L,number-1);
                break;
            }
            default:
                printf("您输入的查找方式有误请确认后再操作");
                break;
        }
        
    }
    //删除指定的学生信息
    void DeletStudent (SqList*L,int i)
    {
        if(i<0||i>sum)
            printf("输入信息有误");
        else
        {
            for (int m=i-1;m<sum;m++)
            {
                L->student[m]=L->student[m+1];
            }
            //删除
            sum--;
            L->length--;
        }
    }
    //更新表中的学生信息
    void ReGetStudent (SqList*L)
    {
        int p;
        printf("请输入需要更新的位置:");
        scanf("%d",&p);
        GetStudent(L, p-1);
    }
    void charu(SqList* L)
    {
        printf("请输入需要插入的位置:");
        int p;
        scanf("%d",&p);
        GetStudent(L, sum);
        sum++;
        for (int i=sum-1;i>p-1;i--)
            jiaohuan(L,i);
        
        
    }
    void jiaohuan(SqList*L,int i)
    {
        long a;
        a=L->student[i-1].id;
        L->student[i-1].id=L->student[i].id;
        L->student[i].id=a;
        char b[64];
        strcpy(b, L->student[i-1].name);
        strcpy(L->student[i-1].name,L->student[i].name);
        strcpy(L->student[i].name, b);
        float c;
        c=L->student[i-1].grade;
        L->student[i-1].grade=L->student[i].grade;
        L->student[i].grade=c;
        
    }
    void paixu (SqList*L)
    {
        printf("请输入排序的要求:0代表学号;1代表成绩");
        int m;
        scanf("%d",&m);
        switch (m) {
            case 0:
                while (1)
                {
                    int f=0,q=0;
                    f=q;
                    for (int i=0;i<sum-1;i++)
                        if (L->student[i].id>L->student[i+1].id)
                        {
                            jiaohuan(L, i+1);
                            f=1;
                        }
                        else f=0;
                    if (f==0)
                        break;
                    
                }
                break;
                
            case 1:
                while (1)
                {
                    int f=0,q=0;
                    f=q;
                    for (int i=0;i<sum-1;i++)
                        if (L->student[i].grade>L->student[i+1].grade)
                        {
                            jiaohuan(L, i+1);
                            f++;
                        }
                    if (f==q)
                        break;
                }
                break;
        }
    }
    
    void qingkong (SqList*L)
    {
        L->length=0;sum=0;
    
        printf("所有数据已经清空");
    }
    
    int main()
    {
        SqList *text=(SqList*)malloc(sizeof(SqList)*10000);
        //为text划分存储空间
        CreatStudent(text);
        printf("共有多少名学生:");
        //录入基础有多少学生
        scanf("%d",&sum);
        text->length=0;
        for (int i=0;i<sum;i++)
            GetStudent(text,i);
        //获得基础学生信息
        int c;
        printf("(1)显示:显示当前所有学生信息记录;\n");
        printf("(2)录入:从键盘输入一条学生信息记录,插入到表中指定的位置;\n");
        printf(" (3)查找:根据学号或者记录的位置查找学生的各项信息;\n");
        printf("(4)删除:删除指定位置的学生信息记录;\n");
        printf("(5)更新:更新指定位置的学生信息记录;\n");
        printf("(6)统计:统计表中学生人数。\n");
        printf(" (7) 排序:按照学号或者绩点进行排序\n");
        printf("(8)清空:清空表中所有记录\n");
        int p=1;
        while (p==1)
        {
            printf("请输入你的操作指令:\n");
            scanf("%d",&c);
            switch (c) {
                case 1:
                    for (int i=0;i<sum;i++)
                        PrintStudent(text,i);
                    break;
                case 2:
                    charu(text);
                    break;
                case 3:
                    FindStudent(text);
                    break;
                case 4:
                {
                    int m;
                    printf("请输入需要删除学生的位置:");
                    scanf("%d",&m);
                    DeletStudent(text, m);
                }
                    break;
                case 5:
                    ReGetStudent(text);
                    break;
                case 6:
                    printf("学生的总数是:%d",sum);
                    break;
                case 7:
                    paixu(text);
                    break;
                case 8:
                    qingkong(text);
                    break;
                case 0:
                    p=0;
                    break;
                default:
                    printf("输入指令不对,请重新输入如果退出请输入0;");
                    break;
            }
        }
    }
    
    

    报告区

    第一部分:实验分析与设计(可加页)
    一、 实验内容描述(问题域描述)
    设计一个学生信息管理系统,实现对学生基本信息的添加、删除、修改和查询等操作,其中每个学生信息包含学号,姓名和绩点。要求系统完成以下主要功能:
    (1)显示:显示当前所有学生信息记录;
    (2)录入:从键盘输入一条学生信息记录,插入到表中指定的位置;
    (3)查找:根据学号或者记录的位置查找学生的各项信息;
    (4)删除:删除指定位置的学生信息记录;
    (5)更新:更新指定位置的学生信息记录;
    (6)统计:统计表中学生人数。
    (7) 排序:按照学号或者绩点进行排序
    (8)清空:清空表中所有记录

    二、 实验基本原理与设计(数据结构设计与算法设计)

    (1) 显示利用栈的顺序遍历输出每一个学生的信息;
    (2) 录入需要先通过遍历找到需要插入的位置,然后获取需要录入的学生的信息,利用尾插法插入该学生信息。
    (3) 查找通过遍历每一个学生的信息和所拥有的数据进行对比最终得出结果
    (4) 删除直接从该位置开始后面的学生信息向前进一
    (5) 先通过查找找到指定位置然后对其中的元素信息进行替换
    (6) 遍历过程中设置一个变量让其每次加一
    (7) 对所需要排序的内容进行比较如果不一致则进行交换并将变量j++;重复循环直到变量j为0;
    (8) 清空令length为0;
    三、主要仪器设备及耗材
    1.PC机
    2.开发环境(比如:VC,Eclipse)
    X-code
    第二部分:实验调试与结果分析(可加页)
    一、 调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等)
    1.调试方法描述
    ① 输入c程序,并保存;
    ② 编译c程序,找出程序的语法错误并改正;
    ③ 输入测试数据,运行c程序;
    ④ 若有错利用断点一步步运行查错
    ⑤ 重复②-④步,直到得到正确的运行结果。

    2.实验输入/输出数据记录
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    4.实验过程发现的问题

    在设计除排序算法外的算法的时候没有什么太大问题;在设计排序算法时,我发现总会出现未完全排序的情况,因为顺序表与链表不同不能排序过程中直接插入,直到我引入了一个新的变量,让他来检验排序是否完全完成;虽然时间复杂度有所上升,但是能较好的完成功能的需要。

    二、 实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)
    1.结果描述
    功能1-8全部都能正常实现;没有意外。
    2.实验现象分析
    所有程序经调试均符合题目要求。
    3.影响因素讨论
    ① 程序的输入提示不够,不知道何时需要输入数据,所以要增加输入提示,提示用户改做什么;
    ② 输出提示不够,输出结果不太清晰;
    4.算法分析(包括时间和空间)
    T(n)=o(n3);
    5.结论
    顺序表便于查找指定位置的内容,也便于顺序查找,但是在插入的时候不是很方便;总体来说这个实验我做的时间不算长但是其中的思路还是花了点时间。顺序表还是很实用的。
    三、 实验小结、建议及体会
    通过这次上机实验,使我对顺序表有了更加深刻的理解,结构体的用法也更加熟练,虽然在编程中出现了很多错误,但是最终错误都得以解决,让我下一次遇到这些问题更加的得心应手。锻炼了我的逻辑能力。
    运用顺序表来写一个学生管理系统,有其优势就是统计显示比较方便快捷,但是也有其劣势那就是录入和删除的繁琐,每一次录入删除需要移动所有数据。但好在在排序上,顺序表的便捷和可读比链表好。
    下一次遇到顺序表和链表的问题时可以多比较一下其各自的时间和空间复杂度,选择更加便捷不容易出错的作为一开始的思路。
    算法在节省空间存储的基础上却又加大了程序运行时间的开销,空间与时间是难以兼得的熊和鱼掌,程序员编写的时候需要考虑侧重点

    展开全文
  • 报告汇总之c语言数据结构报告篇(二) 简单计算器 代码区 #include <stdio.h> #include <stdlib.h> char S[100]; char S2[100]; int i=0; //用来存储计算对数据 typedef struct sqlist { ...

    报告汇总之c语言数据结构报告篇(二)

    简单计算器

    代码区

    #include <stdio.h>
    #include <stdlib.h>
    
    char S[100];
    char S2[100];
    int i=0;
    
    //用来存储计算对数据
    typedef struct sqlist
    {
        char data[100];
        int top;
    }s1;
    //初始化数据栈
    void initSqlist (s1*L)
    {
        L=(s1*)malloc(sizeof(s1));
        L->top=-1;
    }
    //数据栈进栈
    void pushs1 (s1*L,char c)
    {
        L->top++;
        L->data[L->top]=c;
    }
    //数据栈进栈
    int  pop (s1*L)
    {
        int i;
        i=L->top;
        L->top--;
        return L->data[i];
    }
    //创建运算符栈
    typedef struct
    {
        char op[100];
        int top;
    } c1;
    //初始化运算符栈
    void initc1 (c1*P)
    {
        P=(c1*)malloc(sizeof(c1));
        P->top=-1;
    }
    //运算符压栈
     void pushc1 (c1*P,char c)
    {
        P->top++;
        P->op[P->top]=c;
    }
    //运算符出栈
    char popc1 (c1*P)
    {
        int i=P->top;
        P->top--;
        return P->op[i];
    }
    //获得需要处理的式子
    void get (char s1[100])
    {
        int i=0;
        scanf("%s",s1);
        while (s1[i]!=';')
        {
            printf("%c",s1[i]);
            i++;
        }
        printf("\n");
    }
    void changeguohao (char S[100],s1*L,c1*P,int i);
    //变换中缀为后缀
    void change (char S[100],s1*L,c1*P,int i)
    {
        get(S);
        printf("后缀表达式为:");
        char a;
        while (S[i-1]!=';')
        {
            int s=-1;
            if (S[i]=='(')
            {
                    s=P->top;
            }
            if (S[i]=='('||S[i]==')')
            {
                if (S[i]==')')
                {
                    
                    while (P->top!=s)
                    {
                        a=popc1(P);
                        printf("%c",a);
                    }
                }
                i++;
            }
            if (S[i]>=49&&S[i]<=57)
            {
                pushs1(L,S[i]);
                a=pop(L);
                printf("%c",a);
            }
            if (S[i]==';')
                while (P->top!=-1) {
                    a=popc1(P);
                    printf("%c",a);
                }
            if (S[i]=='+'||S[i]=='-')
            {
                if (S[i-2]=='+'||S[i-2]=='-')
                {
                    a=popc1(P);
                    printf("%c",a);
                }
                pushc1(P,S[i]);
            }
            if (S[i]=='*'||S[i]=='/')
            {
                pushc1(P, S[i]);
                if(S[i+1]!='(')
                {
                    i++;
                    pushs1(L,S[i]);
                    a=pop(L);
                    printf("%c",a);
                }
                while (P->top!=-1&&S[i+1]!='(')
                {
                    a=popc1(P);
                    printf("%c",a);
                }
                //i++;
                //pushc1(P,S[i]);
            }
            i++;
        }
    
    }
    //变换有括号时的中缀表达式
    void changeguohao (char S[100],s1*L,c1*P,int i)
    {
        char a;
        if (S[i]==')')
        {
            while (P->top!=-1)
            {
                a=popc1(P);
                printf("%c",a);
            }
            i++;
        }
        change(S, L, P, i);
    }
    //计算后缀表达式
    int clculate (char S[100],s1*L,c1*P,int i)
    {
        printf("请输入您需要处理的后缀表达式:");
        get(S);
        i=0;
        char a;
        char b;
        int c=0;
        char d = '0';
        L->top=-1;
        while (S[i]!=';')
        {
            if (S[i]>=49&&S[i]<=57)
                pushs1(L, S[i]);
            //数据压栈
            else
            {
                //对运算符进行判断,进行计算
                if (S[i]=='+')
                {
                    a=pop(L);
                    b=pop(L);
                    c=(a-'0')+(b-'0');
                    d=c+'0';
                    pushs1(L, d);
                }
                if (S[i]=='-')
                {
                    a=pop(L);
                    b=pop(L);
                    c=(b-'0')-(a-'0');
                    d=c+'0';
                    pushs1(L, d);
                }
                if (S[i]=='*')
                {
                    a=pop(L);
                    b=pop(L);
                    c=(a-'0')*(b-'0');
                    d=c+'0';
                    pushs1(L, d);
                }
                if (S[i]=='/')
                {
                    a=pop(L);
                    b=pop(L);
                    c=(b-'0')/(a-'0');
                    d=c+'0';
                    pushs1(L, d);
                }
            }
            i++;
        }
        return c;
    }
    int main ()
    {
        s1 *L;
        L=(s1*)malloc(sizeof(s1));
        //initSqlist(L);
        L->top=-1;
        c1 *P;
        P=(c1*)malloc(sizeof(c1));
        //initc1(* &P);
        P->top=-1;
        while (1)
        {
            printf("请输入您需要进行的操作:");
            printf("0代表转换为后缀表达式;1代表计算后缀表达式结果\n");
            int n;
            scanf("%d",&n);
            getchar();
            switch (n)
            {
                case 0:
                {
                    printf("中缀表达式为:");
                    change(S, L, P,i);
                    printf("\n");
                    break;
                }
                case 1:
                {
                    
                    printf ("计算的结果为:%d",clculate(S, L, P, i));
                    printf("\n");
                    break;
                }
                default:
                    break;
            }
        }
        return 0;
    }
    
    

    报告区

    一、 实验内容描述(问题域描述)
    编写程序,模拟简单运算器的工作:输入一个算式(没有空格),遇等号“=”说明输入结束,输出结果。假设计算器只能计算加减乘除运算,运算数和结果都是整数。要求完成以下功能:
    (1) 从键盘录入中缀表达式,将中缀表达式转换为后缀表达式输出;
    (2) 输入后缀表达式,计算后缀表达式的值。
    二、实验基本原理与设计(数据结构设计与算法设计)
    (1)利用顺序栈进行存储和运算运算符和数字
    (2)在读入信息时碰到数字就输出,碰到字符先入栈比较后输出
    (3)在进行计算时直接运算,把运算后的结果入栈;直至把最终结果出栈
    第二部分:实验调试与结果分析(可加页)
    一、 调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等)
    1.调试方法描述
    ① 输入c程序,并保存;
    ② 编译c程序,找出程序的语法错误并改正;
    ③ 输入测试数据,运行c程序;
    ④ 若有错利用断点一步步运行查错
    ⑤ 重复②-④步,直到得到正确的运行结果。

    2.实验输入/输出数据记录
    在这里插入图片描述
    3.实验过程发现的问题
    在进行减法运算的时候我们需要注意是谁减谁,除法运算也一样。开始我并没有注意到这一点,导致后面的结果错误很多。
    在把中缀转后缀的过程中我忘记将括号删去导致一开始输出时括号一起输出;带括号的转换
    的复杂程度明显高于不带括号所以我将其单独列出便于查看。
    二、 实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等)
    1. 结果描述
    转换过程和计算过程全部正确;结果输出无误。
    2. 实验现象分析
    所有程序经调试均符合题目要求。
    3.影响因素讨论

    4.算法分析(包括时间和空间)
    空间复杂度为 Sn=O(100)
    时间复杂度为Tn=O(n)
    5.结论
    经过多次调试,所有程序最终运行都成功了。

    三、 实验小结、建议及体会
    学习C语音需要有很大的耐心与毅力,对我们的身体的脑力都是一项很大的挑战。敲了快整整一 周的代码,虽然很累,很烦琐,偶尔还会 被题目难倒,压力山大。可当自己将题目一
    题一题的解决时,心中更多的是成就感,多了一分慰藉。在接下来的日子里,要更加努力好好学专业基础,稳固提升。在课余时间更加注重劳逸结合,多运动,多锻炼,这样学习更有效率。

    展开全文
  • 哈工大数据结构与算法全部实验汇总,包括代码和实验报告,供给广大学弟学妹。学艺不精,有不足的地方希望大家多多包涵,进行改进。
  • 笔者写的 JavaScript 数据结构与算法之美系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习。文中包含了十大经典排序算法的思想、代码实现、一些例子、复杂度分析、动画、还有算法可视化工具。这...
    7e28b335b1b3ce66af34b1a7a644dce2.png
    前言
    算法为王。
    想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手;只有内功深厚者,前端之路才会走得更远。
    笔者写的 JavaScript 数据结构与算法之美系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习。文中包含了十大经典排序算的思想、代码实现、一些例子、复杂度分析、动画、还有算法可视化工具。这应该是目前最全的 JavaScript 十大经典排序算法的讲解了吧。如何分析一个排序算法复杂度分析是整个算法学习的精髓。
    • 时间复杂度: 一个算法执行所耗费的时间。
    • 空间复杂度: 运行完一个程序所需内存的大小。
    学习排序算法,我们除了学习它的算法原理、代码实现之外,更重要的是要学会如何评价、分析一个排序算法。分析一个排序算法,要从 执行效率、内存消耗、稳定性 三方面入手。

    2.1 执行效率

    1. 最好情况、最坏情况、平均情况时间复杂度我们在分析排序算法的时间复杂度时,要分别给出最好情况、最坏情况、平均情况下的时间复杂度。除此之外,你还要说出最好、最坏时间复杂度对应的要排序的原始数据是什么样的。2. 时间复杂度的系数、常数 、低阶我们知道,时间复杂度反应的是数据规模 n 很大的时候的一个增长趋势,所以它表示的时候会忽略系数、常数、低阶。但是实际的软件开发中,我们排序的可能是 10 个、100 个、1000 个这样规模很小的数据,所以,在对同一阶时间复杂度的排序算法性能对比的时候,我们就要把系数、常数、低阶也考虑进来。3. 比较次数和交换(或移动)次数这一节和下一节讲的都是基于比较的排序算法。基于比较的排序算法的执行过程,会涉及两种操作,一种是元素比较大小,另一种是元素交换或移动。所以,如果我们在分析排序算法的执行效率的时候,应该把比较次数和交换(或移动)次数也考虑进去。

    2.2 内存消耗

    也就是看空间复杂度。还需要知道如下术语:
    • 内排序:所有排序操作都在内存中完成;
    • 外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
    • 原地排序:原地排序算法,就是特指空间复杂度是 O(1) 的排序算法。

    2.3 稳定性

    • 稳定:如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变。比如:a 原本在 b 前面,而 a = b,排序之后,a 仍然在 b 的前面;
    • 不稳定:如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序改变。比如:a 原本在 b 的前面,而 a = b,排序之后, a 在 b 的后面;
    十大经典排序算法(上)

    3.1 冒泡排序(Bubble Sort)

    9638fdde7b7043c2e0917eb05745df99.gif
    思想
    • 冒泡排序只会操作相邻的两个数据。
    • 每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。
    • 一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。
    特点
    • 优点:排序算法的基础,简单实用易于理解。
    • 缺点:比较次数多,效率较低。
    实现
    // 冒泡排序(未优化)const bubbleSort = arr => {console.time('改进前冒泡排序耗时');const length = arr.length;if (length <= 1return;// i < length - 1 是因为外层只需要 length-1 次就排好了,第 length 次比较是多余的。for (let i = 0; i 1; i++) {// j < length - i - 1 是因为内层的 length-i-1 到 length-1 的位置已经排好了,不需要再比较一次。for (let j = 0; j 1; j++) {if (arr[j] > arr[j + 1]) {const temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }console.log('改进前 arr :', arr);console.timeEnd('改进前冒泡排序耗时');
    };
    优化:当某次冒泡操作已经没有数据交换时,说明已经达到完全有序,不用再继续执行后续的冒泡操作。
    // 冒泡排序(已优化)const bubbleSort2 = arr => {console.time('改进后冒泡排序耗时');const length = arr.length;if (length <= 1return;// i < length - 1 是因为外层只需要 length-1 次就排好了,第 length 次比较是多余的。for (let i = 0; i 1; i++) {let hasChange = false// 提前退出冒泡循环的标志位// j < length - i - 1 是因为内层的 length-i-1 到 length-1 的位置已经排好了,不需要再比较一次。for (let j = 0; j 1; j++) {if (arr[j] > arr[j + 1]) {const temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    hasChange = true// 表示有数据交换
                }
            }if (!hasChange) break// 如果 false 说明所有元素已经到位,没有数据交换,提前退出
        }console.log('改进后 arr :', arr);console.timeEnd('改进后冒泡排序耗时');
    };
    测试
    // 测试const arr = [78456321];
    bubbleSort(arr);// 改进前 arr : [1, 2, 3, 4, 5, 6, 7, 8]// 改进前冒泡排序耗时: 0.43798828125msconst arr2 = [78456321];
    bubbleSort2(arr2);// 改进后 arr : [1, 2, 3, 4, 5, 6, 7, 8]// 改进后冒泡排序耗时: 0.318115234375ms
    分析
    • 第一,冒泡排序是原地排序算法吗 ?冒泡的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,所以它的空间复杂度为 O(1),是一个原地排序算法。
    • 第二,冒泡排序是稳定的排序算法吗 ?在冒泡排序中,只有交换才可以改变两个元素的前后顺序。为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等的时候,我们不做交换,相同大小的数据在排序前后不会改变顺序。所以冒泡排序是稳定的排序算法。
    • 第三,冒泡排序的时间复杂度是多少 ?最佳情况:T(n) = O(n),当数据已经是正序时。最差情况:T(n) = O(n2),当数据是反序时。平均情况:T(n) = O(n2)。
    动画
    653340f0724de596c8224def34950f54.gif冒泡排序动画

    3.2 插入排序(Insertion Sort)

    插入排序又为分为 直接插入排序 和优化后的 拆半插入排序 与 希尔排序,我们通常说的插入排序是指直接插入排序。一、直接插入思想一般人打扑克牌,整理牌的时候,都是按牌的大小(从小到大或者从大到小)整理牌的,那每摸一张新牌,就扫描自己的牌,把新牌插入到相应的位置。插入排序的工作原理:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。步骤
    • 从第一个元素开始,该元素可以认为已经被排序;
    • 取出下一个元素,在已经排序的元素序列中从后向前扫描;
    • 如果该元素(已排序)大于新元素,将该元素移到下一位置;
    • 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置;
    • 将新元素插入到该位置后;
    • 重复步骤 2 ~ 5。
    实现
    // 插入排序const insertionSort = array => {const len = array.length;if (len <= 1return
        let preIndex, current;for (let i = 1; i         preIndex = i - 1//待比较元素的下标
            current = array[i]; //当前元素while (preIndex >= 0 && array[preIndex] > current) {//前置条件之一: 待比较元素比当前元素大array[preIndex + 1] = array[preIndex]; //将待比较元素后移一位
                preIndex--; //游标前移一位
            }if (preIndex + 1 != i) {//避免同一个元素赋值给自身array[preIndex + 1] = current; //将当前元素插入预留空位
                console.log('array :'array);
            }
        }return array;
    };
    测试
    // 测试const array = [54321];
    console.log("原始 array :"array);
    insertionSort(array);// 原始 array:    [5, 4, 3, 2, 1]// array:           [4, 5, 3, 2, 1]// array:           [3, 4, 5, 2, 1]// array:          [2, 3, 4, 5, 1]// array:           [1, 2, 3, 4, 5]
    分析
    • 第一,插入排序是原地排序算法吗 ?插入排序算法的运行并不需要额外的存储空间,所以空间复杂度是 O(1),所以,这是一个原地排序算法。
    • 第二,插入排序是稳定的排序算法吗 ?在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。
    • 第三,插入排序的时间复杂度是多少 ?最佳情况:T(n) = O(n),当数据已经是正序时。最差情况:T(n) = O(n2),当数据是反序时。平均情况:T(n) = O(n2)。
    动画b24e982e6960659574828806ed5b287a.gifinsertion-sort.gif二、拆半插入插入排序也有一种优化算法,叫做拆半插入。思想折半插入排序是直接插入排序的升级版,鉴于插入排序第一部分为已排好序的数组,我们不必按顺序依次寻找插入点,只需比较它们的中间值与待插入元素的大小即可。步骤
    • 取 0 ~ i-1 的中间点 ( m = (i-1) >> 1 ),array[i] 与 array[m] 进行比较,若 array[i]  <  array[m],则说明待插入的元素 array[i]  应该处于数组的 0 ~ m 索引之间;反之,则说明它应该处于数组的 m ~ i-1 索引之间。
    • 重复步骤 1,每次缩小一半的查找范围,直至找到插入的位置。
    • 将数组中插入位置之后的元素全部后移一位。
    • 在指定位置插入第 i 个元素。
    注:x >> 1 是位运算中的右移运算,表示右移一位,等同于 x 除以 2 再取整,即 x >> 1 == Math.floor(x/2) 。
    // 折半插入排序const binaryInsertionSort = array => {const len = array.length;if (len <= 1return;
        let current, i, j, low, high, m;for (i = 1; i         low = 0;
            high = i - 1;
            current = array[i];while (low <= high) {//步骤 1 & 2 : 折半查找
                m = (low + high) >> 1// 注: x>>1 是位运算中的右移运算, 表示右移一位, 等同于 x 除以 2 再取整, 即 x>>1 == Math.floor(x/2) .if (array[i] >= array[m]) {//值相同时, 切换到高半区,保证稳定性
                    low = m + 1//插入点在高半区
                } else {
                    high = m - 1//插入点在低半区
                }
            }for (j = i; j > low; j--) {//步骤 3: 插入位置之后的元素全部后移一位array[j] = array[j - 1];
                console.log('array2 :', JSON.parse(JSON.stringify(array)));
            }array[low] = current; //步骤 4: 插入该元素
        }
        console.log('array2 :', JSON.parse(JSON.stringify(array)));return array;
    };
    测试
    const array2 = [54321];console.log('原始 array2:', array2);
    binaryInsertionSort(array2);// 原始 array2:  [5, 4, 3, 2, 1]// array2 :     [5, 5, 3, 2, 1]// array2 :     [4, 5, 5, 2, 1]// array2 :     [4, 4, 5, 2, 1]// array2 :     [3, 4, 5, 5, 1]// array2 :     [3, 4, 4, 5, 1]// array2 :     [3, 3, 4, 5, 1]// array2 :     [2, 3, 4, 5, 5]// array2 :     [2, 3, 4, 4, 5]// array2 :     [2, 3, 3, 4, 5]// array2 :     [2, 2, 3, 4, 5]// array2 :     [1, 2, 3, 4, 5]
    注意:和直接插入排序类似,折半插入排序每次交换的是相邻的且值为不同的元素,它并不会改变值相同的元素之间的顺序,因此它是稳定的。三、希尔排序希尔排序是一个平均时间复杂度为 O(n log n) 的算法,会在下一个章节和 归并排序、快速排序、堆排序 一起讲,本文就不展开了。

    3.3 选择排序(Selection Sort)

    思路选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。步骤
    • 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
    • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
    • 重复第二步,直到所有元素均排序完毕。
    实现
    const selectionSort = array => {const len = array.length;
        let minIndex, temp;for (let i = 0; i 1; i++) {
            minIndex = i;for (let j = i + 1; j             if (array[j] array[minIndex]) {// 寻找最小的数
                    minIndex = j; // 将最小数的索引保存
                }
            }
            temp = array[i];array[i] = array[minIndex];array[minIndex] = temp;
            console.log('array: 'array);
        }return array;
    };
    测试
    // 测试const array = [54321];
    console.log('原始array:'array);
    selectionSort(array);// 原始 array:  [5, 4, 3, 2, 1]// array:           [1, 4, 3, 2, 5]// array:           [1, 2, 3, 4, 5]// array:          [1, 2, 3, 4, 5]// array:           [1, 2, 3, 4, 5]
    分析
    • 第一,选择排序是原地排序算法吗 ?选择排序空间复杂度为 O(1),是一种原地排序算法。
    • 第二,选择排序是稳定的排序算法吗 ?选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。所以,选择排序是一种不稳定的排序算法。
    • 第三,选择排序的时间复杂度是多少 ?无论是正序还是逆序,选择排序都会遍历 n2 / 2 次来排序,所以,最佳、最差和平均的复杂度是一样的。最佳情况:T(n) = O(n2)。最差情况:T(n) = O(n2)。平均情况:T(n) = O(n2)。
    动画0c9cae7ffdd894e7ab453e69691d2cf5.gifselection-sort.gif

    3.4 归并排序(Merge Sort)

    思想排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。归并排序采用的是分治思想。分治,顾名思义,就是分而治之,将一个大问题分解成小的子问题来解决。小的子问题解决了,大问题也就解决了。
    80011440e6518c3050d394361d8be541.pngmerge-sort-example.png
    注:x >> 1 是位运算中的右移运算,表示右移一位,等同于 x 除以 2 再取整,即 x >> 1 === Math.floor(x / 2) 。
    实现
    const mergeSort = arr => {//采用自上而下的递归方法const len = arr.length;if (len 2) {return arr;
        }// length >> 1 和 Math.floor(len / 2) 等价let middle = Math.floor(len / 2),
            left = arr.slice(0, middle),
            right = arr.slice(middle); // 拆分为两个子数组return merge(mergeSort(left), mergeSort(right));
    };const merge = (left, right) => {const result = [];while (left.length && right.length) {// 注意: 判断的条件是小于或等于,如果只是小于,那么排序将不稳定.if (left[0] <= right[0]) {
                result.push(left.shift());
            } else {
                result.push(right.shift());
            }
        }while (left.length) result.push(left.shift());while (right.length) result.push(right.shift());return result;
    };
    测试
    // 测试const arr = [34438547153626272464195048];console.time('归并排序耗时');console.log('arr :', mergeSort(arr));console.timeEnd('归并排序耗时');// arr : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]// 归并排序耗时: 0.739990234375ms
    分析
    • 第一,归并排序是原地排序算法吗 ?这是因为归并排序的合并函数,在合并两个有序数组为一个有序数组时,需要借助额外的存储空间。实际上,尽管每次合并操作都需要申请额外的内存空间,但在合并完成之后,临时开辟的内存空间就被释放掉了。在任意时刻,CPU 只会有一个函数在执行,也就只会有一个临时的内存空间在使用。临时内存空间最大也不会超过 n 个数据的大小,所以空间复杂度是 O(n)。所以,归并排序不是原地排序算法。
    • 第二,归并排序是稳定的排序算法吗 ?merge 方法里面的 left[0] <= right[0] ,保证了值相同的元素,在合并前后的先后顺序不变。归并排序是稳定的排序方法。
    • 第三,归并排序的时间复杂度是多少 ?从效率上看,归并排序可算是排序算法中的佼佼者。假设数组长度为 n,那么拆分数组共需 logn 步,又每步都是一个普通的合并子数组的过程,时间复杂度为 O(n),故其综合时间复杂度为 O(n log n)。最佳情况:T(n) = O(n log n)。最差情况:T(n) = O(n log n)。平均情况:T(n) = O(n log n)。
    动画
    999662a55905dc5adf81f9ed36650c3f.gifmerge-sort.gif

    3.5 快速排序 (Quick Sort)

    快速排序的特点就是快,而且效率高!它是处理大数据最快的排序算法之一。思想
    • 先找到一个基准点(一般指数组的中部),然后数组被该基准点分为两部分,依次与该基准点数据比较,如果比它小,放左边;反之,放右边。
    • 左右分别用一个空数组去存储比较后的数据。
    • 最后递归执行上述操作,直到数组长度 <= 1;
    特点:快速,常用。缺点:需要另外声明两个数组,浪费了内存空间资源。实现方法一:
    const quickSort1 = arr => {if (arr.length <= 1) {return arr;
        }//取基准点const midIndex = Math.floor(arr.length / 2);//取基准点的值,splice(index,1) 则返回的是含有被删除的元素的数组。const valArr = arr.splice(midIndex, 1);const midIndexVal = valArr[0];const left = []; //存放比基准点小的数组const right = []; //存放比基准点大的数组//遍历数组,进行判断分配for (let i = 0; i         if (arr[i]             left.push(arr[i]); //比基准点小的放在左边数组
            } else {
                right.push(arr[i]); //比基准点大的放在右边数组
            }
        }//递归执行以上操作,对左右两个数组进行操作,直到数组长度为 <= 1return quickSort1(left).concat(midIndexVal, quickSort1(right));
    };const array2 = [54321];console.log('quickSort1 ', quickSort1(array2));// quickSort1: [1, 2, 3, 4, 5]
    方法二:
    // 快速排序const quickSort = (arr, left, right) => {let len = arr.length,
            partitionIndex;
        left = typeof left != 'number' ? 0 : left;
        right = typeof right != 'number' ? len - 1 : right;if (left         partitionIndex = partition(arr, left, right);
            quickSort(arr, left, partitionIndex - 1);
            quickSort(arr, partitionIndex + 1, right);
        }return arr;
    };const partition = (arr, left, right) => {//分区操作let pivot = left, //设定基准值(pivot)
            index = pivot + 1;for (let i = index; i <= right; i++) {if (arr[i]             swap(arr, i, index);
                index++;
            }
        }
        swap(arr, pivot, index - 1);return index - 1;
    };const swap = (arr, i, j) => {let temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    };
    测试
    // 测试const array = [54321];
    console.log('原始array:'array);const newArr = quickSort(array);
    console.log('newArr:', newArr);// 原始 array:  [5, 4, 3, 2, 1]// newArr:     [1, 4, 3, 2, 5]
    分析
    • 第一,快速排序是原地排序算法吗 ?因为 partition() 函数进行分区时,不需要很多额外的内存空间,所以快排是原地排序算法。
    • 第二,快速排序是稳定的排序算法吗 ?和选择排序相似,快速排序每次交换的元素都有可能不是相邻的,因此它有可能打破原来值为相同的元素之间的顺序。因此,快速排序并不稳定。
    • 第三,快速排序的时间复杂度是多少 ?极端的例子:如果数组中的数据原来已经是有序的了,比如 1,3,5,6,8。如果我们每次选择最后一个元素作为 pivot,那每次分区得到的两个区间都是不均等的。我们需要进行大约 n 次分区操作,才能完成快排的整个过程。每次分区我们平均要扫描大约 n / 2 个元素,这种情况下,快排的时间复杂度就从 O(nlogn) 退化成了 O(n2)。最佳情况:T(n) = O(n log n)。最差情况:T(n) = O(n2)。平均情况:T(n) = O(n log n)。
    动画
    fef6158047c355b5b647c5a8c20a39c5.gifquick-sort.gif
    解答开篇问题快排和归并用的都是分治思想,递推公式和递归代码也非常相似,那它们的区别在哪里呢 ?
    9a8e071b3da14ad7323205fb45529454.png快速排序与归并排序
    可以发现:
    • 归并排序的处理过程是由下而上的,先处理子问题,然后再合并。
    • 而快排正好相反,它的处理过程是由上而下的,先分区,然后再处理子问题。
    • 归并排序虽然是稳定的、时间复杂度为 O(nlogn) 的排序算法,但是它是非原地排序算法。
    • 归并之所以是非原地排序算法,主要原因是合并函数无法在原地执行。
    • 快速排序通过设计巧妙的原地分区函数,可以实现原地排序,解决了归并排序占用太多内存的问题。
    还没结束这篇文章只列举了十大经典排序算法的一半哦。笔者为了写好这系列的文章,花费了大量的业余时间,边学边写,边写边修改,前后历时差不多 2 个月,入门级的文章总算是写完了。ps:记得看下一篇Oo(今日推送第四条)- END -8ed4611e7e2dd9978433addad7d17a12.png
    展开全文
  • 实验名称 访问者模式的应用 日期 2018年 04 月2 日 ...某公司OA系统中包含一个员工信息管理子系统,该公司员工包括正式员工和临时工,每周人力资源部和财务部等部门需要对员工数据进行汇总汇总数据包括员工工...

    实验名称             访问者模式的应用                    日期 2018 04 2

    一、实验目的:

    1) 掌握访问者模式(Visitor)的特点

    2) 分析具体问题,使用访问者模式进行设计。

     

     

    某公司OA系统中包含一个员工信息管理子系统,该公司员工包括正式员工和临时工,每周人力资源部和财务部等部门需要对员工数据进行汇总,汇总数据包括员工工作时间、员工工资等。该公司基本制度如下:

    (1) 正式员工每周工作时间为40小时,不同级别、不同部门的员工每周基本工资不同;如果超过40小时,超出部分按照100元/小时作为加班费;如果少于40小时,所缺时间按照请假处理,请假所扣工资以80元/小时计算,直到基本工资扣除到零为止。除了记录实际工作时间外,人力资源部需记录加班时长或请假时长,作为员工平时表现的一项依据。

    (2) 临时工每周工作时间不固定,基本工资按小时计算,不同岗位的临时工小时工资不同。人力资源部只需记录实际工作时间。

    人力资源部和财务部工作人员可以根据各自的需要对员工数据进行汇总处理,人力资源部负责汇总每周员工工作时间,而财务部负责计算每周员工工资。

    现使用访问者模式设计该员工信息管理子系统。

    JAVA语言实现(C#控制台应用程序实现)该模式。绘制该模式的UML图。

     

    二、实验环境:

     

     

     

    三、实验内容:

    【模式UML图】

     

     

     

     

    【模式代码】

    ​
    package 实验10;
    
    public class Client {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            EmployeeList list = new EmployeeList();
            Employee fte1,fte2,fte3,pte1,pte2;
    
            fte1 = new FulltimeEmployee("张无忌", 3200.00, 45);
            fte2 = new FulltimeEmployee("杨过", 2000.00, 40);
            fte3 = new FulltimeEmployee("段誉", 2400.00, 38);
            pte1 = new ParttimeEmployee("洪七公", 80.00, 20);
            pte2 = new ParttimeEmployee("郭靖", 60.00, 18);
    
            list.addEmployee(fte1);
            list.addEmployee(fte2);
            list.addEmployee(fte3);
            list.addEmployee(pte1);
            list.addEmployee(pte2);
    
            Department dep;
            dep = (Department)XMLUtil.getBean();
            list.accept(dep);
        }
    
    }
    
    ​
    package 实验10;
    
    public abstract class Department {
        public abstract void visit(FulltimeEmployee employee);
        public abstract void visit(ParttimeEmployee employee);
    
    }
    
    package 实验10;
    
    public interface Employee {
        public void accept(Department handler);
    }
    
    package 实验10;
    
    import java.util.ArrayList;
    
    public class EmployeeList {
        public ArrayList<Employee> list = new ArrayList<Employee>();
        public void addEmployee(Employee employee) {
            list.add(employee);
        }
    
        public void accept(Department handler) {
            for(Object obj : list) {
                ((Employee)obj).accept(handler);
            }
        }
    }
    
    package 实验10;
    
    public class FADepartment extends Department{
        public void visit(FulltimeEmployee employee) {
            int workTime  = employee.getWorkTime();
            double weekWage = employee.getWeeklyWage();
            if(workTime > 40) {
                weekWage = weekWage + (workTime - 40)*100;
            }
            else if(workTime < 40) {
                weekWage = weekWage - (40 - workTime)*80;
                if(weekWage < 0) {
                    weekWage = 0;
                }
            }
            System.out.println("正式员工" + employee.getName() + "实际工资为:" + weekWage + "元。");
        }
        public void visit(ParttimeEmployee employee) {
            int workTime = employee.getWorkTime();
            double hourWage  = employee.getHourWage();
            System.out.println("临时工"+employee.getName()+"实际工资为:"+workTime*hourWage+"元");
        }
    
    }
    
    package 实验10;
    
    public class FulltimeEmployee implements Employee{
        private String name;
        private double weeklyWage;
        private int workTime;
    
        public FulltimeEmployee(String name,double weeklyWage,int workTime) {
            this.name = name;
            this.weeklyWage = weeklyWage;
            this.workTime = workTime;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setWeeklyWage(double weeklyWage) {
            this.weeklyWage = weeklyWage;
        }
    
        public void setWorkTime(int workTime) {
            this.workTime = workTime;
        }
    
        public String getName() {
            return (this.name);
        }
    
        public double getWeeklyWage() {
            return (this.weeklyWage);
        }
    
        public int getWorkTime() {
            return (this.workTime);
        }
    
        public void accept(Department handler) {
            handler.visit(this);
        }
    }
    
    package 实验10;
    
    public class HRDepartment extends Department {
    
        public void visit(FulltimeEmployee employee) {
            int workTime  = employee.getWorkTime();
            System.out.println("正式员工"+employee.getName()+"实际工作时间为:"+workTime+"小时");
            if (workTime > 40) {
                System.out.println("正式员工"+employee.getName()+"加班时间为:"+(workTime-40)+"小时");
            }
            else if(workTime < 40){
                System.out.println("正式员工"+employee.getName()+"请假时间为:"+(40 - workTime)+"小时");
            }
        }
    
        public void visit(ParttimeEmployee employee) {
            int workTime = employee.getWorkTime();
            System.out.println("临时工"+employee.getName()+"实际工作时间"+workTime+"小时");
        }
    }
    
    package 实验10;
    
    public class ParttimeEmployee implements Employee{
        private String name;
        private double hourWage;
        private int workTime;
    
        public ParttimeEmployee(String name,double hourWage,int workTime) {
            this.name = name;
            this.hourWage = hourWage;
            this.workTime = workTime;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setHourWage(double hourWage) {
            this.hourWage = hourWage;
        }
    
        public void setWorkTime(int workTime) {
            this.workTime = workTime;
        }
    
        public String getName() {
            return (this.name);
        }
    
        public double getHourWage() {
            return (this.hourWage);
        }
    
        public int getWorkTime() {
            return (this.workTime);
        }
    
        public void accept(Department handler) {
            handler.visit(this);
        }
    }
    

     

    package 实验10;
    
    import javax.xml.parsers.*;
    import org.w3c.dom.*;
    import org.xml.sax.SAXException;
    import java.io.*;
    
    public class XMLUtil {
        public static Object getBean() {
            try {
                //创建DOM文档对象
                DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = dFactory.newDocumentBuilder();
                Document doc;
                doc = builder.parse(new File("D:\\软件集合\\IntelliJ IDEA Community Edition 2018.3.2\\JAVA\\JAVA\\src\\实验10\\config.xml"));
    
                //获取包含类名的文本节点
                NodeList nl = doc.getElementsByTagName("className");
                Node classNode=nl.item(0).getFirstChild();
                String cName=classNode.getNodeValue();
    
                //通过类名生成实例对象并将其返回
                Class c=Class.forName(cName);
                Object obj=c.newInstance();
                return obj;
            }
            catch(Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    

     

    【运行截图】

    第一种结果

    <?xml version="1.0" encoding="UTF-8" ?>
    <config>
        <className>实验10.FADepartment</className>
    </config>
    

    第二种结果

    <?xml version="1.0" encoding="UTF-8" ?>
    <config>
        <className>实验10.HRDepartment</className>
    </config>
    

    四、心得体会:

    访问者模式主要适用于以下情况:

    1. 一个对象结构包含多个类型的对象,希望对这些对象实施一些依赖其具体类型的操作
    2. 需要对一个对象结构中的对象进行很多不同的且不相关的操作,并需要避免让这些操作“污染”这些对象的类,也不希望在增加新的操作时修改这些类
    3. 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作

     

     

     

     

     

    展开全文
  • (按顺序)每周作业链接汇总 第一周:算法分析 第二周:栈 第三周:队列 第四周:列表 第五周:查找和排序 第六周:树 ...实验一 实验名称:线性结构实验报告 实验二 实验名称:树实验报告 实验...
  • 实验报告链接汇总 团队项目报告链接汇总 代码托管链接 课堂项目实践或课后作业 课堂的收获和不足 问卷调查 每周作业链接汇总 每周作业目录 第一周作业 第二周作业 第三周作业 第四周作业 第五周作业 第六周...
  • 三、实验报告链接汇总 四、代码托管链接 五、课堂项目实践 六、加分项目 七、扣分项目 八、课程收获与不足 九、给开学初的我和学弟学妹们的学习建议 十、问卷调查 十一、对谢涛老师的工作给矛评价或建议 十二、总结...
  • 四、实验报告链接汇总 五、代码托管链接 六、课堂项目实践 七、课程收获与不足 八、问卷调查 九、总结中涉及到的链接的二维码 一、每周作业链接汇总 第一周作业:学习教材第十二章,初步了解软件工程,完成第一周...
  • 20172319 2018.09.03-12.25 ...实验报告链接汇总 团队项目报告链接汇总 代码托管链接 课堂项目实践 课程收获与不足 问卷调查 其他任意发挥 给出你的总结中涉及到的链接的二维码 每周作业链接汇总 第1周学习总...
  • 2.实验报告链接汇总 3.团队项目报告链接汇总 4.代码托管链接 5.课堂项目实践 6.课程收获与不足 7.给出你的总结中涉及到的链接的二维码 (按顺序)每周作业链接汇总 预备作业1 简要内容:对上学期的总结和对本专业...
  • 计原课设报告

    2012-12-07 14:50:13
    这是个计算机原理课设的实验报告。包含了主机系统总体结构框图 数据通路结构设计图 各部件详细设计图 机器指令 指令格式和寻址方式 微程序控制部件设计 指令汇总 心得体会
  • 2017-2018-1 实验报告目录: 1 2 3 4 5  课程名称:《程序设计与数据结构》  学生班级:1623班  学生姓名:刘伟康  学生学号:20162330  实验时间:2017年10月23日—2017年10月27日  实验...
  • 2017-2018-1 实验报告目录: 1 2 3 4 5  课程名称:《程序设计与数据结构》  学生班级:1623班  学生姓名:刘伟康  学生学号:20162330  实验时间:2017年11月6日  实验名称:查找与排序 ...
  • 医友检验管理系统(KJLis2013),帮助检验医生很方便出色地完成中文报告单的审核、打印、查询、统计、汇总数据备份等工作,其报表编辑功能可以满足各地区医生的要求。 该软件易安装、便操作、数据安全、运行稳定等...
  • 每周读书笔记链接汇总实验报告链接汇总代码托管团队项目-小组名称:javawokres-博客链接:- java项目workers的博客-代码托管链接:- javaworkers数据结构实验-课程收获与不足自己的收获:对于自己来说,java这门课程...
  • 实验报告链接汇总 团队项目报告链接汇总 代码托管链接 课堂项目实践 课程收获与不足 问卷调查 总结中涉及到的链接的二维码 每周作业链接汇总 第一周作业:   何以改善程序算法,何以使算法变得又快又好等等...
  • 摘要相关工具、cocoNLP信息抽取工具、国内电话号码正则匹配、清华大学XLORE:中英文跨语言百科知识图谱、清华大学人工智能技术系列报告、自然语言生成、NLU太难了系列、自动对联数据及机器人、用户名黑名单列表、罪名...
  • 来自MySQL AB公司的统计报告显示,MySQL的安装数量已超过800万,每天的下载量接近5万人次。  MySQL正迅速成为系统集成商首选的数据库系统。据SD Times报上的一篇文章报道,对900多位读者进行的调查表明,MySQL在...
  • 2.5.4 半结构数据模型 30 第3章 Oracle DBA的UNIX/Linux基础 31 3.1 UNIX和Linux操作系统概述 31 3.1.1 UNIX 31 3.1.2 Linux 32 3.1.3 中档系统 32 3.2 理解UNIX shell 33 3.3 访问UNIX系统 33 3.4...
  • 软件工程教程

    2012-07-06 23:10:29
    考核方式: 课程设计(附设计说明文档,正文字数不少于1000字)(60%)+平时作业及实验(30%)+平时表现(10%),按优秀、良好、中、及格、不及格五级评定成绩 通过演示及讲述,讲解课程设计的整体情况,针对其设计提出一些技术...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

数据结构实验报告汇总

数据结构 订阅