成电UNIX编程作业三部曲---第一曲内存中构建10叉非完全存储数

17 篇文章 0 订阅

研一报了段老师的“UNIX环境高级编程”课程,感觉非常棒。学到了很多东西,对操作系统有了新的认识。不过是被大家尊称为“大理段王爷”的段大牛,讲课犹如行云流水,游刃有余。虽然课程只有一个学分,但是内容还是很充实的,要学好不容易。推荐考核方式是考察,不过课上听段王爷说居然有一个人报的考试偷笑。。。其胆量令段王爷也敬佩三分。三道结课作业设计的很不错,几乎把讲课内容都涉及到了,论文提交后一直想拿出来给大家分享,可是考虑到分数还没出来,所以(怕老师不允许贴到网上来给我弄挂)一直存在电脑里面。转眼快一年了,今天突然学姐问我多线程问题才让我想起来。顺手把它贴上来吧,虽然有点low,不过对巩固基础知识还是很有好处的,特别是作业3线程池。

PS: 如果今年题目没变,恰巧又被可爱的师弟师妹到了,请不要直接copy啊,还是自己撸出来好


好了,不多说,看第一题吧。

题目:在内存中构建一个10叉非完全树T10,树的高度为7,叶子节点的高度差最多为1,将该树T10存储到一个树存储文件Ftree中去。编写读树文件Ftree的程序,将树读入到内存中来,并且检验树的正确性。
性能分析说明:
1.空间复杂度
2.文件大小
3.内存重构树的时间。


源码上上来,振振精神得意

1.程序源码

(1)创建10叉非完全数的程序源码

//Progarm one:creat the tree

 

#include<stdio.h>

#include<stdlib.h>

#define TEN 10

#define MAXLEVEL 8         

typedef structTreeNode *TenTree;

struct TreeNode{

    int     data;

    TenTree   children[TEN];

}NTree;

 

int num = 1;

voidpreorder(TenTree ptr)

{

    if (ptr){

        printf("%d ",ptr->data);

        for (int i = 0; i < TEN; i++){

            preorder(ptr->children[i]);

        }

    } else {

        printf("0 ");

    }

}

 

TenTreeCreatTree(int level)

{

    TenTree T;

    if (level == MAXLEVEL){

        T = NULL;

        return T;

    }

 

    T = (TenTree)malloc(sizeof(NTree));

    T->data = num++;

    for (int i = 0; i < TEN; i++){

        T->children[i] = CreatTree(level+1);

    }

    return T;

}

 

int main()

{

    TenTree T;

    T = CreatTree(1);

    preorder(T);

    return 0;

}

(2)内存搭建树的程序源码

//Progarm two: creat the tree

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "apue.h"

#define TEN 10 
#define MAXLEVEL 8

typedef struct TreeNode *TenTree;
struct TreeNode{
    int     data;
    TenTree   children[TEN];
}NTree;

int flag = 0;  //flag reply the correction of the tree ,0 is correct,1 is right
int pre_data = -1;
int fd = -1; 

void print(int data)
{
    char str[10];
    sprintf(str, "%d ",data);
    if (write(fd, str, strlen(str)) == -1){
        printf("cannot write\n");
    }
}

void preorder_print(TenTree ptr)
{
    if (ptr){
        print(ptr->data);
        for (int i = 0; i < TEN; i++){
            preorder_print(ptr->children[i]);
        }
    } else {
        print(0);
    }
}

void preorder_check(TenTree ptr)
{
    if (ptr){
        if (ptr->data > pre_data)
            pre_data = ptr->data;
        else
            flag = 1;
        for (int i = 0; i < TEN; i++){
            preorder_check(ptr->children[i]);
        }
    } 
}

TenTree CreatTree(int level)
{
    int data = 0;
    int is_leaf = 0;
    TenTree T;
    if (level > MAXLEVEL)
        flag = 1;

    if (scanf("%d",&data) == EOF){
        T = NULL;
        return T;
    }
       

    if (data != 0){
        T = (TenTree)malloc(sizeof(NTree));
        T->data = data;
        for (int i = 0; i < TEN; i++){
            if ((T->children[i] = CreatTree(level+1)) != NULL)
                is_leaf = 1;
        }
        if ((!is_leaf) && (level < (MAXLEVEL-2)))
            flag = 1;
    } else {
        T = NULL;
    }
    return T;
}

int main()
{
    TenTree T;
    printf("Now the tree is building ...\n");
    T = CreatTree(1);
    preorder_check(T);
    
    if ((fd = open("tree_result", O_WRONLY|O_CREAT, FILE_MODE)) < 0){
        printf("cannot open this file: tree_result\n");
        return 0;
    }
    preorder_print(T);
    close(fd);


    printf("The tree is built successfully\n");
    if (flag == 0)
        printf("This tree is right\n");
    else
        printf("This tree is wrong\n");
    return 0;
}


2.性能分析

(1)程序运行时截屏


对于第一个程序而言,讲它建立的树先存放在Ftree文件中。

由于创建的文件太大,无法全部截屏,选取文件头和文件尾分别截屏:

 

对于第二个程序运行时截屏:


说明:为了方面在截屏中展示程序的正确性,本人将内存中建立好的树打印在tree_result中,可以很方便的用md5sum命令看出建立的树与输入的树是否一致,并且在程序中也检测了建立的树是否满足题目要求以及正确性。检测的方法在稍后讨论。

 

查看Ftree文件与生成的tree_result文件的MD5值:

 

(2)设计思路

程序一设计思路:在创建10叉非完全树时,我们用输出0表示空节点,输出非空整数表示该节点。创建方式借鉴先序遍历的方法进行,同时按照先序遍历从1依次递增输出各个节点,遇到空节点输出0,按照此方式,讲运行结果重定向的输出到Ftree文件中。

程序二设计思路:从Ftree中按照先序遍历的方式创建十叉树,遇到0整数则创建空节点,在创建过程中,当层数超过最大层数时,则将错误标志置1。对于叶子节点间不超过1层的条件,我们利用树结构的特点,转化成在7层的树,叶子节点所在层不能小于6层。在preorder_check()函数中判断,当该节点为叶子节点,同时层数小于6时也将flag置1。在结构正确的前提下,对于判断建立的树正确与否,我们利用输入数的特性,在先序遍历中,要求之前遍历的节点值要小于后面的值,如果错误,也将flag置1。对于满10叉树的情况,这种方法可以唯一确定该树。同时,为了更加直观的测试,在程序中将构建好的10叉树输出到tree_result文件中。

 

(3)空间复杂度

   空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。

   对于存储算法本身所占用的存储空间,从creattree.c这个文件来说,只有700多个字节,不到1KB,可见文件大小非常小,creattrre.c这个文件运行过程中生成的文件大小也是非常小,trre.c这个文件只有2.1KB,同样ttrre.c这个文件运行过程中生成的文件大小也是非常小。

   对于算法的输入输出数据所占用的存储空间,算法本身输入的数据为建立树的过程中输入的数据,存储在树的各个节点中;算法的输出数据其中之一为输出到荧屏的提示信息,例如 “The tree is built successfully”,这样虽然在空间复杂度上作出了一点点牺牲,但是给用户带来的信息量却是很大的,带来了很大的方便;另外的输出数据为输出到文件中的数据,从上面文件大小的分析中可知,数据占用的数据量并不大。

   对于算法在运行过程中临时占用的存储空间,程序编译后运行的过程中是一定会占用内存的,程序一与程序二运行过程中所占用的临时空间主要为定义变量、结构体、10叉树以及程序本身运行所需要的内存空间,可以看出,运行过程并不会占用太大的内存空间。

 

(4)文件大小

源文件的大小:


树文件Ftree的大小:

 

  
  
由于空节点用0表示,所以在输出文件中会存在大量的0,但是这并不会增加内存构建树的开销,因为在构建树时,我们用NULL表示空节点,并不申请堆空间。当然也可以进一步优化,节约存储空间。

 

(5)内存重构树的时间

去除程序中写入测试文件的时间,我们可以看到tree.c文件运行时:


看到时钟时间为1.643s。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值