数据结构初步

数据结构

  • 逻辑结构
  • 线性结构:线性表,栈,队列,串,数组
  • 非线性结构:树结构,图结构
  • 物理存储结构
  • 顺序结构
  • 链式结构
  • 索引结构
  • 散列结构

节点拥有的子树数目称为节点的度;
度为0则是叶子节点或者终端节点;
树的度是树内各节点的度的最大值;

  • 结点的层次:根为第一层,根的孩子为第二层;节点的最大层次称为树的深度或者高度
  • 树的存储
  • 双亲表示法:假设以一组连续空间存储树的节点,同时在每个节点中,附设一个指示器指示其双亲结点到的链表中的位置;也就是说每个结点除了知道自己是谁,还知道自己的双亲是谁
  • dataparent
    数据域,存储节点数据信息指针域,指示存储该节点的双亲在数组中的下标
#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode {
        TElemtype data;  //结点数据
        int parent;     //双亲位置
}PTNode;
typedef struct {      //树结构
    PTNode nodes[MAX_TREE_SIZE];     //结点数组
    int r, n;                        //根的位置和结点数
}PTree;

  • 孩子表示法:每个结点有多个指针域,其中每个指针指向一个树的根结点,我们把这种方法叫做多重链表表示法
  • 把每个结点的孩子结点排列起来,以单链表作存储结构,则n个节点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中; 孩子表示法
    设计2种结点数据
  • 孩子结点
  • childnext
    数据域,存储某个节点在表头数组中下标指针域,用来存储指向该节点的下一个孩子结点的指针
  • 表头数组的表头结点
  • childfirstchild
    数据域,存储节点数据信息头指针域,用来存储该节点的孩子链表的头指针
  • 双亲孩子表示法
  • ![孩子双亲表示法](https://img-blog.csdn.net/20170508231452384?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTEM5MDA3MzA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
    满二叉树
    所有分支结点都存在左子树和右子树,并且所有叶子节点都在同一层,这样的二叉树称为满二叉树; ![满二叉数](https://img-blog.csdn.net/20170508232149950?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTEM5MDA3MzA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
    完全二叉树
    一棵具有n个节点的二叉树,如果编号i(1
    typedef int TElemtype;
    typedef struct BiTNode
    {
        TElemtype data;
        struct BiTNode *lchild, *rchild;
    
    }BiTNode,*BiTree; 

    二叉链表的结点

    二叉树遍历

    指的是从根结点遍历,按照某种顺序依次访问二叉树中的所有结点,使得每个结点被访问依次且被访问一次。
    这里有2个关键词:次序和访问;我们用图形形式来表现树的结构,但是对计算机来说只有循环和判断等来处理;

  • 前序遍历:先访问根结点,在前序遍历左子树,在右字树
  • 中序遍历:先左子树,然后根结点,然后是右子数
  • 后序遍历:先左子树,然后右结点,然后是根结点
  • 层序遍历:第一层开始访问,从上到下
  • 前序遍历算法

    二叉树的定义是递归,所以实现遍历算法也可以实现递归;

    typedef int TElemtype;
    typedef struct BiTNode
    {
        TElemtype data;
        struct BiTNode *lchild, *rchild;
    }BiTNode,*BiTree; 
    void PreOrderTraverse(BiTree T) {
        if (T == NULL) {
            return;
        }
        printf("%c", T->data);      //显示结点数据,可以更改为对其他结点操作
        PreOrderTraverse(T->lchild);//先序遍历左子树
        PreOrderTraverse(T->rchild);//最后先序遍历右子树
    }

    中序遍历算法

    //二叉树中序遍历算法
    typedef int TElemtype;
    typedef struct BiTNode
    {
        TElemtype data;
        struct BiTNode *lchild, *rchild;
    }BiTNode,*BiTree; 
    void InOrderTraverse(BiTree T) {
        if (T == NULL) {
            return;
        }
        PreOrderTraverse(T->lchild);//中序遍历左子树
        printf("%c", T->data);      //显示结点数据,可以更改为对其他结点操作
        PreOrderTraverse(T->rchild);//最后中序遍历右子树
    }

    二叉树的建立

    //建立二叉树,也是利用了递归的原理。

    typedef int TElemtype;
    typedef struct BiTNode
    {
        TElemtype data;
        struct BiTNode *lchild, *rchild;
    }BiTNode,*BiTree; 
    
    void CreateBiTree(BiTree *T) {
        TElemtype ch;
        scanf("%c", &ch);
        if (ch == '#'){
            *T = NULL;
        }
        else {
            *T = (BiTree)malloc(sizeof(BiTNode));
            if (!*T) {
                exit(OVERFLOW);
            }
            else {
                (*T)->data = ch;
                CreateBiTree(&(*T)->lchild);     //构造左子树
                CreateBiTree(&(*T)->rchild);     //构造右子树
            }
        }
     }

    线索二叉树

    指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树(Threaded Binary Tree)

    我们如何知道某一结点的lchild是指向左孩子还是直接前驱?rchild是指向右孩子还是指向后驱?因此我们需要在每个结点在增加2个标志位ltag和rtag,其中ltag和rtag只存放0或者1数字的布尔型变量;结构如下

    lchildltagdatartagrchild
    ltag为0时候指向结点左孩子,为1指向结点的前驱
    rtag为0时候指向结点右孩子,为1时候指向结点后驱
    /*Link==0表示指向左右孩子指针;Thread==1表示指向前驱后后驱的线索
    typedef enum(Link,Thread) PointerTag;   
    typedef struct BiThrNode(){
        TElemType data;  //结点数据
        struct BiThrNode *lchild,*rchild;   //左右孩子指针
        PointerTag LTag;    //左标志
        PointerTag RTag;   //右标志
    }BiThrNode,*BiThrTree;

    线索化的实质上就是将二叉链表中的空指针改为指向前驱或者后继的线索。由于前驱和后继的信息只有在遍历该二叉树的时候才能得到,所以线索化的过程就是在遍历的过程中修改空指针的过程。

    BiThrTree pre;//全局变量,始终指向刚刚访问过的结点
    /*中序遍历进行中序线索化*/
    void InThreading(BiThrTree p){
        if(p){
            InThreading(p->lchild); /*递归左子树线索化*/
            if(!p->lchild){         /*没有左孩子*/
                p->LTag=Thread;    //前驱线索
                p->lchild=pre;     /*左孩子指针指向前驱*/
            }
            if(!pre->rchild){      /*前驱没有右孩子*/
                pre->RTag=Thread;
                pre->rchild=p;       /*前驱右孩子指针指向后继(当前结点p)*/ 
            }   
            pre=p;
            InThreading(p->rchild);      /*递归右子树线索化*/ 
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了复习数据结构和Java编程语言,你可以按照以下步骤进行: 1. 确保你已经掌握了Java SE的基础知识。这包括Java的语法、数据类型、流程控制语句、面向对象编程等。如果你需要巩固这些基础知识,可以通过阅读相关的教材或参加在线课程来加强你的理解。 2. 接下来,你可以进一步了解JDBC(Java Database Connectivity)。JDBC是Java用于与数据库进行交互的标准API。你可以学习如何连接到数据库、执行SQL查询和更新操作,并了解如何处理结果集。有关JDBC的更多信息,可以查阅Java官方文档或参考相关的教程。 3. 数据结构中的树形结构是非常重要的一部分。确保你对树的概念和常见的树结构(如二叉树、AVL树、B树等)有一个清晰的理解。你可以阅读关于树的教材或参考在线资源来加深你对树的理解。 4. 如果你想进一步学习数据库建模和设计,可以初步了解PowerDesigner数据库建模工具的使用。这个工具可以帮助你设计和管理数据库模型,并生成相应的DDL脚本。 5. 最后,了解UML(Unified Modeling Language)统一建模语言也是非常有帮助的。UML是一种用于描述和设计软件系统的标准化语言。了解UML的基本概念和常用的建模图形(如类图、时序图、用例图等)将使你能够更好地理解和交流软件系统的设计。 通过按照上述步骤进行复习,你将能够深入了解数据结构和Java编程,并为进一步的学习和实践打下坚实的基础。记得多进行实践和练习,以加深对知识的理解和应用。祝你学习顺利!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值