• 二叉树,约瑟夫,多项式合并!


    2015.2.9
    星期一 晴

    树的基本概念:

    度数:一个节点的子树的个数为该节点的度数,一颗数的度数是指该树中节点的最大度数
    树叶或者终端节点:度数为0的节点
    高度或者深度:节点的层数等于父节点的层数加1,根节点的层数定义为1,树中节点层数最大值称为该树的高度或者深度
    有序树:若树中每个节点的各子树的排列为从左到右,不能交换,即兄弟之间是有序的,则称该树为有序树
    满二叉树:深度为K时有2^k-1个节点的二叉树
    完全二叉树:只有最下面两层就度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上。

    对于完全二叉树有以下特点: 设节点数为n,某节点编号为i

    数组实现:如果有N个节点需要N+1个数组空间,把数组0的位置空出来,从1开始排列,利用下面的公式计算每个i节点子节点的下标:
    左子节点:2*i,右子节点:2*i+1;

    满足:2*i<=n时,i子节点存在左孩子,且编号为2*i
    满足:2*i+1<=n时,i子节点存在左孩子,且编号为2*i

    用链表和递归函数实现一个树的创建:中间有很多打印的程序,方便看过程。
    #include <stdio.h>
    #include <stdlib.h>

    typedef char bt_data_t;

    typedef struct tree_node_t{
    bt_data_t data;
    struct tree_node_t *lchild,*rchild;
    }bitree_t;

    bitree_t *Create_Bitree(int i, bt_data_t a[],int n);

    static int indent = 0;
    static int step = 0;

    int main()
    {
    bt_data_t bt_array[] = {0,'a','b','c','d','e','f','g','h','i','j'};
    bt_data_t bt_array[] = {0,'a','b','c',0,0,0,0,'h','i','j'}; //将数组改成非完全二叉树,补0

    bitree_t *root;
    printf("Begin creating B-tree ... ");

    root = Create_Bitree(1,bt_array,sizeof(bt_array)/sizeof(bt_data_t) - 1); //从根节点开始,调用递归函数创建二叉树的所有节点并插入数据
    printf("Finished! ");

    return 0;
    }

    bitree_t *Create_Bitree(int i,bt_data_t a [],int n) //递归函数的创建
    {
    bitree_t *root;
    int j;

    printf("-------------->step<%2d> ",step++);

    indent++;

    root = (bitree_t *)malloc(sizeof(bitree_t));
    root->data = a[i]; //将数据写入结构体
    printf("%d*cRoot(%c) ",indent,'-',root->data);

    j = 2*i;
    if(j <= n) //对于非完全而二叉树这样修改:if(j <= n && a[j] != '0') //判断是否存在左子树
    {
    printf("%*cRoot(%d)->Left(%d) ",indent,'-',i,j);
    root->lchild = Create_Bitree(j, a, n);
    }
    else
    {
    printf("%*cRoot(%d)->Left(NULL) ",indent,'-',i);
    root->lchild = NULL; //不存在左子树,怎返回NULL
    }

    j = 2*i+1;
    if(j <= n) //对于非完全而二叉树这样修改:if(j <= n && a[j] != '0') //判断是否存在右子树
    {
    printf("%*cRoot(%d)->Right(%d) ",indent,'-',i,j);
    root->rchild = Create_Bitree(j, a, n);
    }
    else
    {
    printf("%*cRoot(%d)->Right(NULL) ",indent,'-',i);
    root->rchild = NULL;
    }

    indent--;

    printf("<--------------step<%2d> ",step++);

    return root;
    }

    执行效果:

    lg@lg-desktop:/mnt/hgfs/source test/pdf$ gcc bt_create1.c
    lg@lg-desktop:/mnt/hgfs/source test/pdf$ ./a.out
    Begin creating B-tree ...
    -------------->step< 0>
    1*cRoot(-)
    -Root(1)->Left(2)
    -------------->step< 1>
    2*cRoot(-)
    -Root(2)->Left(4)
    -------------->step< 2>
    3*cRoot(-)
    -Root(4)->Left(8)
    -------------->step< 3>
    4*cRoot(-)
    -Root(8)->Left(NULL)
    -Root(8)->Right(NULL)
    <--------------step< 4>
    -Root(4)->Right(9)
    -------------->step< 5>
    4*cRoot(-)
    -Root(9)->Left(NULL)
    -Root(9)->Right(NULL)
    <--------------step< 6>
    <--------------step< 7>
    -Root(2)->Right(5)
    -------------->step< 8>
    3*cRoot(-)
    -Root(5)->Left(10)
    -------------->step< 9>
    4*cRoot(-)
    -Root(10)->Left(NULL)
    -Root(10)->Right(NULL)
    <--------------step<10>
    -Root(5)->Right(NULL)
    <--------------step<11>
    <--------------step<12>
    -Root(1)->Right(3)
    -------------->step<13>
    2*cRoot(-)
    -Root(3)->Left(6)
    -------------->step<14>
    3*cRoot(-)
    -Root(6)->Left(NULL)
    -Root(6)->Right(NULL)
    <--------------step<15>
    -Root(3)->Right(7)
    -------------->step<16>
    3*cRoot(-)
    -Root(7)->Left(NULL)
    -Root(7)->Right(NULL)
    <--------------step<17>
    <--------------step<18>
    <--------------step<19>
    Finished!


    用函数指针可以给已经写好的函数增加额外的功能!!!!!!!!!!!

    将数组data_t array[] = {0,'A','B','C','D','E','0','F','0','0','G','H','0','0','I'};中的字符插入数的相应位置,
    并按照不同的遍历顺序打印出来:依次先序,中序,后序;

    #include <stdio.h>
    #include <stdlib.h>

    typedef int data_t;

    typedef struct tree{
    data_t data;
    struct tree *lchild;
    struct tree *rchild;
    }bitree_t;

    bitree_t *Create_Bitree(int i,data_t a[],int n);
    void Pre_Order(bitree_t *bt);
    void In_Order(bitree_t *bt);
    void Post_Order(bitree_t *bt);

    main()
    {
    data_t array[] = {0,'A','B','C','D','E','0','F','0','0','G','H','0','0','I'};
    bitree_t *root;
    int len;

    len = sizeof(array)/sizeof(data_t) - 1;
    printf("begain create b-tree.... ");

    root = Create_Bitree(1,array,len);

    printf("finish ");

    printf("Pre_Order = ");
    Pre_Order(root);
    putchar(' ');
    printf("In_Order = ");
    In_Order(root);
    putchar(' ');
    printf("Post_Order = ");
    Post_Order(root);
    putchar(' ');


    }

    bitree_t *Create_Bitree(int i,data_t a[],int n) //建立树的程序和上面的程序一样
    {
    bitree_t *root;
    int j;

    root = (bitree_t *)malloc(sizeof(bitree_t));
    if(root == NULL)
    {
    return NULL;
    }

    root->data = a[i];

    j = 2 * i;
    if((j <= n) && a[j] != '0')
    {
    root->lchild = Create_Bitree(j,a,n); //递归创建
    }
    else
    {
    root->lchild = NULL;
    }

    j = 2 * i + 1;
    if((j <= n) && a[j] != '0')
    {
    root->rchild = Create_Bitree(j,a,n); //递归创建
    }
    else
    {
    root->rchild = NULL;
    }

    return root;
    }

    void Pre_Order(bitree_t *bt) //先序遍历二叉树,并打印出找到的数据
    {
    if(bt == NULL)
    {
    return ;
    }
    printf("%3c",bt->data); //根节点
    Pre_Order(bt->lchild); //左子树
    Pre_Order(bt->rchild); //右子树

    //return ;
    }

    void In_Order(bitree_t *bt) //中序遍历二叉树,并打印出找到的数据
    {
    if(bt == NULL)
    {
    return ;
    }
    In_Order(bt->lchild); //左子树
    printf("%3c",bt->data);//根节点
    In_Order(bt->rchild); //右子树
    }

    void Post_Order(bitree_t *bt) //先序遍历二叉树,并打印出找到的数据
    {
    if(bt == NULL)
    {
    return ;
    }
    Post_Order(bt->lchild); //左子树
    Post_Order(bt->rchild); //右子树
    printf("%3c",bt->data); //根节点

    }


    执行效果:

    lg@lg-desktop:/mnt/hgfs/source test/pdf$ gcc testtree.c
    lg@lg-desktop:/mnt/hgfs/source test/pdf$ ./a.out
    begain create b-tree....
    finish
    Pre_Order = A B D E G H C F I
    In_Order = D B G E H A C I F
    Post_Order = D G H E B I F C A
    lg@lg-desktop:/mnt/hgfs/source test/pdf$


    约瑟夫问题的链表的实现:
    #include <stdio.h>
    #include <stdlib.h>

    void joseph(int n, int k, int m) //总共n个人,从第k个人的下一个开始作为1,数到m的人出局
    {
    int i;
    linklist_t p,L,r;
    L = NULL;

    for(i = 1; i <= n; i++) //建立循环链表
    {
    p = (linklist_t)malloc(sizeof(linknode_t));
    p->data = i;
    if(L == NULL)
    {
    L = p;
    }
    else
    {
    r->next = p;
    }
    r = p;
    }

    for(i = 1; i < k; i++) //找到第一个开始计数的位置
    {
    r = r->next;
    }
    while(r->next != r) //人数大于1
    {
    for(i = 1; i <= m-2; i++) //这里是一个技巧性很强的操作,巧妙地利用已有的指针释放出局的数据,避免了利用额外的指针来做标记动作
    {
    r = r->next;
    }
    p = r->next;
    r->next = p->next;
    printf("%d",p->data);
    free(p);
    r = r->next;
    }
    printf("%d ",r->data);

    }

    多项式的表示和相加:这里的操作很很特别,用两个结构体组成一个完整的多项式的表示,包括多项式的系数,指数,和指向下一个节点的指针

    #include <stdio.h>
    #include <stdlib.h>

    typedef struct{ //这个结构体中包括了多项式的系数,指数
    float coaf;
    int exp;
    }data_t;

    typedef struct node{ //第二个结构体包括了第一个结构体和一个指向下个节点的指针
    data_t data;
    struct node *next;
    }linknode_t;*linklist_t;

    void Addpoly(linklist_t pa,linklist_t pb) //这个函数时多项式的所有项进项操作,包括从小到大的排序和合并的过程,一次性全部完成。
    {
    linklist_t pre,u;
    float sum;

    pre = pa;
    pa = pa->next;

    u = pb;
    pb = pb->next;

    free(u);

    while(pa && pb)
    {
    if(pa->data.exp < pb->data.exp) //将小的多项式放在结构体的前面
    {
    pre->next = pa;
    pre = pa;
    pa = pa->next;
    }

    if(pa->data.exp > pb->data.exp)
    {
    pre->next = pb;
    pre = pb;
    pb = pb->next;
    }
    else
    {
    sum = pa->data.coaf + pb->data.coaf; //合并多项式的系数
    if(sum != 0.0)
    {
    pa->data.coaf = sum;
    pre->next = pa;
    pre = pa;
    pa = pa->next;
    }
    else
    {
    u = pa; //当节点合并后的系数为0后,删除相应的节点pa
    pa = pa->next;
    free(u);
    }

    u = pb; //删除相应的节点pa
    pb = pb->next;
    free(u);
    }

    }
    if(pa != NULL) //当其中一个节点遍历完毕后,将还有数据的链表直接放到合并后的链表的后面
    {
    pre->next = pa;
    }
    else
    {
    pre->next = pb;
    }
    }

    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************

  • 相关阅读:
    D365: 笔记(VS无法打开表浏览器)
    D365: 笔记(跟踪调试批处理代码)
    D365: 笔记(非批处理执行class中弹出交互式窗体或报表)
    D365: 笔记(现有量增加批号表字段查询条件)
    D365: 新功能(二)采购发票自动化流程
    D365: 新功能(一)按日期设置编号规则
    ES6 入门教程(未完)
    深入理解TypeScript(未完)
    项目
    vue + threejs 项目踩坑总结
  • 原文地址:https://www.cnblogs.com/cnlg/p/4282656.html
Copyright © 2020-2023  润新知