• 数据结构 (二叉树)1


    二叉树:每个节点最多有两棵字数,左子树和右子树

    完全二叉树:叶节点只能出现在最下层和次下层,而且最下面一层的结点都集中在该层最左边的若干位置的二叉树。每层节点都完全填满,在最后一层上如果不是满的,则只缺少右边的若干节点。

    满二叉树:要么叶子节点,要么节点同时具有左右子树

    存储方式:

    1)顺序存储: 遍历速度上有优势,但占空间大,是非主流二叉树。二叉树通常以链式存储

        typedef char datatype;

        typedef struct node{

             datatype data;

             int lchild, rchild;

            int parent;

       } Node;

    Node tree[Length];

    2)链式存储: 

        typedef char datatype;

        typedef struct node{

       datatype data;

      struct node *lchild;

          struct node *rchild;

       }node;

    node *tree;

    二叉树的遍历

    前序遍历:根节点->左子树->右子树

    中序遍历:左子树->根节点->右子树

    后序遍历:左子树->右子树->根节点

    实现:

    问题:

    取地址符&

      int a=0;

      int *p=&a;

      int *M=& 0X01000; wrong, 对于一个数值常量,没有地址。 变量有地址要有一个存储单元对变量进行标识

    引用&

      int a=0;

      int &r=a;

    new delete 和malloc free: new 是operator, malloc是函数

    创建:

    void creatBinTree(node * t)
    {
    char c;
    cin>>c;
    if(c=='#')
    t=NULL;
    else
    {
    // t=(node *) malloc(sizeof(node *));
    t=new node;
    t->data=c;
    creatBinTree(t->lchild);
    creatBinTree(t->rchild);
    }
    
    }
    
    
    
    int main()
    {
    
    node * tree1;
    creatBinTree(tree1);
    
    visit(tree1);
    return 0;
    }

    错误,tree没有创建成功,因为没有改变tree;

    将函数改为:

    void creatBinTree(node * &t)

    成功

    分析:

    C++中的值传递,指针传递,引用传递

    1)值传递:

      形参是实参的拷贝,改变形参的值不会影响外部实参的值(如果函数内部需要修改参数,并且不希望这个改变影响其他调用,采用值传递)

    2)指针传递:

         形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行操作。

    3)引用传递

        形参相当于实参的“别名”, 对形参的操作,就是对实参的操作。在引用传递过程中,被调函数的形式参数虽然作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。

    void change1(int n)
    {
    
        cout<<"值传递--函数操作地址"<<&n<<endl;
        n++;
        }
    void change2(int &n)
    {
        cout<<"引用传递--函数操作地址"<<&n<<endl;
        n++;
    }
    
    void change3(int *n)
    {
        cout<<"指针传递--函数操作地址"<<n<<endl;
        *n=*n+1;
    }
    int main()
    {
        int n=10;
        cout<<"实参的地址"<<&n<<endl;
        change1(n);
        cout<<n<<endl;
        change2(n);
        cout<<n<<endl;
        change3(&n);
        cout<<n<<endl;
        return 0;
    }

    引用于指针传递的区别:

    1)引用被创建的同时必须被初始化(指针可在任何时候初始化)

    2)不能有NULL引用,必须有合法的存储单元关联

    3)引用一旦初始化,就不能改变引用的关系(指针可以随时改变所指的对象)

    指针传递的本质是值传递,传递一个地址值。

    1)递归方式访问二叉树:

    void visit(node * root)
    {
        if(root)
        {
            cout<<root->data<<endl;
            if(root->lchild)
            {
                visit(root->lchild);
            }
    
            if(root->rchild)
            {
                visit(root->rchild);
            }
        }
    }

    2)非递归的访问二叉树:

    (递归操作遍历过的根节点还要回来,所以需要存起来)-->栈存储  

      对于前序遍历,优先访问根节点,然后在分别访问左孩子和右孩子。

      对于任一节点P:

      1)访问节点P,并将节点P入栈;

      2)判断节点P的左孩子是否为空,若为空,则取栈顶节点并出栈,将栈顶节点的右孩子置为当前的节点P,看其是否为空,若不为空,则循环1), 如为空,则继续出栈。

        若左子树不为空,将P的左孩子置为当前的节点P,重复1)

      3)直到P为NUL并且栈为空

    存在栈中是为了倒叙访问右节点

    ABD入先后入栈,并在入栈时输出,

    D的左孩子为空,将D出栈,但不输出,将其有孩子作为当前节点,为空,将B出栈,并将右节点E作为当前节点,入栈,输出E。

    E和D情况相同,类推。。。

    void preOrder2(node *root)
    {
        stack <node*>s;
        node * p=root;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                s.push(p);
                cout<<p->data<<endl;
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                s.pop();
                p=p->rchild;
            }
        }
    
    }

    中序遍历为出栈的时候再输出

    后序遍历稍稍复杂

  • 相关阅读:
    Java实现HadoopHA集群的hdfs控制
    Hadoop-2.8.5的HA集群搭建
    Python实现bing必应壁纸下载
    使用Python3将Markdown(.md)文本转换成 html、pdf
    使用GitHub作Free图床
    JavaMail实践--实现邮件发送
    Python3实现图片转字符画
    Java编写的Java编辑器_JavaIDE
    Java实现简易版计算器
    Java实现Excel表格操作--API:jxl
  • 原文地址:https://www.cnblogs.com/fanhaha/p/7051958.html
Copyright © 2020-2023  润新知