UNIX C 链表实现族谱图

#include <stdio.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

static unsigned long int next = 1; /* 种子*/

struct GNode            //节点结构体
{
    int tag;            //是否有孩子
    int id;             //id 唯一,用于标记这头牛
    int gend;           //性别 0:male,1:female
    int son_num;        //儿子数量
    int offset;         //相对于页面的偏移量
    int level;          //标记这头牛在族谱图中的位置
    int width;          //以本头牛为根节点的树的宽度,用于控制输出
    struct GNode * sublist;     //子节点链表头
    struct GNode * next;        //下一个节点
};

struct level                    //用于存储一层的牛的信息的链表的结构体
{
    struct GNode * data;
    struct level * next;
};
int rand1 (void)                //生成随机数,用于赋值id
{
    /* 产生伪随机数癿魔术般癿公弅 */
    next = next * 1103515245 + 12345;
    return (unsigned int ) (next / 65536) % 32768;
}
void srand1 (unsigned int seed)
{
    next = seed;
}

int getRandom (void)
{
    if(next == 1)
        srand1 ((unsigned int) time(0)); /* 初始化种子 */
    return rand1();
}


bool id_ava(int id,int list[])     //查看ID是否已被用过
{
    bool flag=true;
    for(int i=0;i<sizeof(list);i++)
    {
        if(id==list[i])
            flag=false;
    }
    return flag;
}

struct GNode * getCow(int n)
{
    struct GNode * head = malloc(sizeof(struct GNode));         //链表头,没有内容
    struct GNode * currcow ;
    struct GNode * cow_g[n];           //用于存储公牛的数组
    struct GNode * cow_m[n];            //用于存储母牛的数组
    int num_g = 0;
    int num_m = 0;
    int num_tot=0;      //当前已经生产的牛数量
    int idList[n];      //已用id 列表
    int index_f;
    int index_m;

    for(int i=0;i<n;i++)
    {
        struct GNode * newcow = malloc(sizeof(struct GNode));
        int temp = getRandom();
        while(num_tot!=0&&!id_ava(temp,idList))
        {
            temp = getRandom();
        }
        idList[i] = temp;
        num_tot++;
        newcow->id = temp;      //结构体初始化
        newcow->tag = 0;
        newcow->son_num=0;
        newcow->next = NULL;
        newcow->offset=0;
        newcow->gend = (getRandom())%2;     //随机赋值性别
        
        if(num_g&&num_m)                    //如果在这之前已有公牛和母牛,则随机制定父母
        {
            index_f=getRandom()%num_g;
            index_m=getRandom()%num_m;
            if(index_f>n||index_m>n)
                printf("KKKKKKKKKKKKKKKKKKKKKKKKKKK\n");
            cow_g[index_f]->tag=1;

            if(cow_g[index_f]->son_num==0)
                cow_g[index_f]->sublist = newcow;       //将其添加到指定父亲节点的子节点链表的末尾,母亲节点则不存储
            else
            {
                struct GNode * bro_temp = cow_g[index_f]->sublist;
                while(bro_temp->next)
                {
                    bro_temp=bro_temp->next;
                }
                bro_temp->next= newcow;
            }
            (cow_g[index_f]->son_num)++;
            cow_m[index_m]->tag=1;
            cow_m[index_m]->son_num++;
            newcow->level = (cow_g[index_f]->level+1);
            printf("~~id=[%d]~~father=[%d]~~~~~\n",newcow->id,cow_g[index_f]->id);
        }
        else
        {
            newcow->level = 1;              //如果在这之前,没有公牛或者没有母牛,就不能指定父亲母亲,只能将其放到第一层
            if(i==0)
            {
                head->next=newcow;
                currcow = newcow;
            }
            else
            {
                currcow->next=newcow;
                currcow = newcow;
            }
        }
        if(newcow->gend==0)     //如果把“==”写成"=",则该判别式始终为0
        {
            cow_g[num_g]=newcow;        //如果是公牛,则添加到公牛数组中
            num_g++;
        }
        else
        {
            cow_m[num_m]=newcow;        //如果是母牛....
            num_m++;
        }
        newcow = NULL;                  //释放指针
    }
    return head;
}


struct level * getdepth(struct GNode * cow,int dep)     //获取cow节点之下的第dep层的节点列表,这里其实只用到dep=2 的情况
{
    struct GNode * tmp;
    struct GNode * fath;
    struct level * lev_head = malloc(sizeof(struct level));   //
    lev_head->next = NULL;
    lev_head->data = NULL;
    struct level * lev_curr = lev_head;
    fath = cow;
    while(fath)
    {
        if(fath->gend==0)
        {
            tmp = fath;
            int i;
            for(i=1;(tmp->sublist)&&(i<dep);i++)
            {
                tmp = tmp->sublist;
            }
            if((i==dep)&&tmp)
            {
                struct level * newmem = malloc(sizeof(struct level));
                newmem->data = tmp;
                newmem->next = NULL;
                if(lev_head->next==NULL)
                {
                    lev_head->next=newmem;
                    lev_curr = newmem;
                }
                else
                {
                    lev_curr->next = newmem;
                    lev_curr = newmem;
                }
            }
        }
        fath = fath->next;
    }
    return lev_head;
}

struct level * getNextLev(struct level * head)              //根据这一层的节点列表,获取下一层的节点列表
{
    struct level * res = malloc(sizeof(struct level));
    res->data=NULL;
    res->next=NULL;

    struct level * curbro;
    if(head->next==NULL)
    {
        printf("NULL POINTER !\n");
        return NULL;
    }
    struct level * bros = head->next;
    struct GNode * bro_data ;
    int i = 0;
    while(bros)
    {
        bro_data = bros->data;
        while(bro_data)
        {
            if(bro_data->tag!=0&&(bro_data->sublist))
            {
                struct GNode *test = bro_data->sublist;
                while(test)
                {
                    test = test->next;
                }
                struct level * newbro = malloc(sizeof(struct level));
                newbro->data=bro_data->sublist;
                if(res->next==NULL)
                {
                    res->next=newbro;
                    curbro = newbro;
                }
                else
                {
                    newbro->next=curbro->next;
                    curbro->next = newbro;
                    curbro = newbro ;
                }
            }
            bro_data = bro_data->next;
        }
        bros = bros->next;
    }
    return res;
}


int getWid(struct GNode * node)     //这里是用的迭代的办法,其实不想用的,最后没办法才用的,还希望大神可以指点一下,应该有其他办法
{
    int wid = 3;
    struct GNode * node_tmp;
    if(node->sublist==NULL)
    {
        return 8;
    }
    else
    {
        node_tmp = node->sublist;
        while(node_tmp)
        {
            wid += getWid(node_tmp);
            node_tmp = node_tmp->next;
        }
    }
    return wid;
}
void printLevel(struct GNode * head)
{
    char * extra ;
    int wid;
    int space = 0;
    printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n");
    if(head->next==NULL)
    {
        printf("Empty list!\n");
        return;
    }
    struct GNode * first_level = head->next;            //先把第一层打印出来,第一层和下面的层不一样,不打印连接符
    while (first_level)
    {
        wid = getWid(first_level);
        if(first_level->id < 1000)  extra = "  ";
        if(first_level->id>999&&first_level->id<10000)  extra = " ";
        if(first_level->id > 9999)  extra = "";
        first_level->offset = space;

        if(first_level->gend==0)
        {
            printf("[%d%s] %*s",first_level->id,extra,wid-8,wid==8?"":" ");     //控制每个id以及中括号一共7个字符宽度
            if(first_level->sublist)
                first_level->sublist->offset=first_level->offset+3;
        }
        else
        {

            printf("(%d%s) ",first_level->id,extra);                            //公牛打印中括号,母牛打印圆括号
        }
        space += wid;
        first_level = first_level->next;
    }
    printf("\n");

    struct level * cur_level = getdepth(head,2);            //先获取第二层的所有牛,放在一个链表里面,再依次往下获取
    struct level * bros;
    struct GNode * bro_data;
    while(cur_level->next)                  //依次循环各层
    {

        bros = cur_level->next;
        space = 0;
        while(bros)                         //依次循环各层内的各个level结构体
        {
            bro_data = bros->data;
            int index = 0;
            while(bro_data)                 //依次循环各个level结构体中的GNode结构体
            {
                wid = getWid(bro_data);
                if(bro_data->id < 1000)
                    extra = "  ";
                else if(bro_data->id>999&&bro_data->id<10000)
                    extra = " ";
                else if(bro_data->id > 9999)
                    extra = "";

                if(index == 0)                              //一头公牛的所有子牛都是放在一个链表里面的,第一头子牛前面是“L”,用index来判断
                {
                    if((bro_data->offset)<space)
                    {
                        printf("S");                        //之前版本会出现这种情况,把getwid()函数写成迭代后,就不会出现这种情况了,但是保险起见还是放在这,没删去
                    }

                    printf("%*s",(bro_data->offset)-space,((bro_data->offset)-space)==0?"":" ");
                    printf("L");
                    space = (bro_data->offset) + 1;
                }
                else
                {
                    bro_data->offset = space;
                    printf("-");
                    space += 1;
                }

                if(bro_data->gend==0)                       //公牛id打印完,需要打印占位符"-",跟后面的兄弟连起来
                {

                    if(bro_data->sublist)
                    {
                        bro_data->sublist->offset = bro_data->offset+3;
                    }
                    printf("[%d%s]",bro_data->id,extra);

                    if(bro_data->next)                      //如果后面还有兄弟的话,就打印'-',没有的话打印空格
                    {
                        for(int i=0 ;i<wid-8 ;i++)
                        {
                            printf("%c",'-');
                        }
                    }
                    else
                    {
                        for(int i=0 ;i<wid-8 ;i++)
                        {
                            printf("%c",' ');
                        }
                    }
                }
                else
                {
                    printf("(%d%s)",bro_data->id,extra);
                }

                space += wid-1;
                bro_data = bro_data->next;
                index++;
            }
            bros = bros->next;
        }
        printf("\n");
        cur_level = getNextLev(cur_level);
    }

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

int main(int argc , char * argv[])
{
    int cow_num = atoi(argv[1]);
    struct GNode *  cows = getCow(cow_num);
    printLevel(cows);
    return 0;
}

执行语句:

gcc -std=c99 PED.c -o ped
./ped 100 > test.txt

打印在txt中的显示效果(由于长度原因,这里只截取到左边一部分):


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值