数据结构-2

  线性表结束了,接下来是树,  其实线性结构就是树的一种特殊情况,

而我们的正常学习顺序也是从特殊到一般,所以也是理所应当的开始了解树的概念。

  树:


  基本概念

  1. 结点的度:子树个数
  2. 树的度:树的所有结点中最大的度数
  3. 叶结点:度为0的结点(没有子树)
  4. 父结点:子节点的上一级结点
  5. 子结点:父节点的子节点
  6. 兄弟结点:拥有同一个父节点
  7. 路径和路径长度:两个节点之间边的数量
  8. 子孙结点:一个结点往下所有结点都是子孙结点
  9. 祖先结点:拥有子孙结点的就是所有子孙结点的祖先结点
  10. 结点的层次:根节点在1层,其他任一结点的层数是其父节点+1
  11. 树的深度:该树中所有节点中,最大的层次就是这棵树的深度

我看对于树,这个考核大纲中,树的下面,只有二叉树...:

  • 树的定义和术语。
  • 二叉树(完全二叉树、满二叉树)的定义和性质、二叉树的存储结构(顺序表示法和二叉链表表示法)。
  • 二叉树遍历的递归算法。
  • 树和森林转换为二叉树的方法。

所以我也只去实现这里面的内容了。


  二叉树

什么是二叉树,二叉树的定义是?二叉树就是每个结点度最大为2的树,并且对于子结点有左右之分,(通俗的说:每个结点最多开俩叉的树)    PS:其实还有空树。

二叉树的性质?

  • 二叉树第i层最大结点数为  2 ^ ( i - 1 ) ,
  • 总结点数为 2 ^ i  - 1  (i ≥ 1)    PS:其实就是二进制...
  • n0 , n1, n2,分别代表一棵树中按度的数量分类的集合,如n0就是度为0的结点数量。有n0+n1+n2=所有结点,n0+n1+n2-1=边的数量   n0=n2+1(抽象理解,,假设:每有一个n0变成了n2,便会增加一个n0,而变成n1不影响n0数量,那么为什么n0比n2多一个呢,请参考一颗仅有一个n0的树,然后再把n0变成n2,会多出两个n0,因为第一个n2必须建立在有一个n0的基础上,它不能凭空产生,所以n0一定会比n2多一个)

二叉树的存放方式?数组(顺序存储结构),链表

二叉树的主要操作集?是否为空IsEmpty,遍历Traversal(*重要),创建Create

  PS:遍历Traversal类型先序中序后序层次

数组实现:

#include <iostream>
using namespace std;

struct Tree
{
    int* arr;
    int lastIndex;
    void Init()
    {
        arr=(int*)malloc(sizeof(int)*64);//为了方便写成固定
        lastIndex = 0;
        for (int i = 0; i < 64; i++)
        {
            arr[i] = 0x7fffffff;
        }
    }
    void Add(int num)
    {
        arr[++lastIndex] = num;
    }
    void Remove(int i)
    {
        if(i<=lastIndex)
        arr[i] = 0x7fffffff;
    }
    int GetLChild(int i)
    {
        return i * 2;
    }
    int GetRChild(int i)
    {
        return i * 2 + 1;
    }
    void PreTraversal(int root)
    {
        if ( arr[root]==0x7fffffff)return;
        cout <<" ["<< arr[root]<<"] ";
        PreTraversal(GetLChild(root));
        PreTraversal(GetRChild(root));
    }
    void MidTraversal(int root)
    {
        if (arr[root] == 0x7fffffff)return;
        MidTraversal(GetLChild(root));
        cout << " [" << arr[root] << "] ";
        MidTraversal(GetRChild(root));
    }
    void LastTraversal(int root)
    {
        if (arr[root] == 0x7fffffff)return;
        LastTraversal(GetLChild(root));

        LastTraversal(GetRChild(root));
        cout << " [" << arr[root] << "] ";
    }
    void LayelTraversal(int root)
    {
        for (int i = 1; i < lastIndex+1; i++)
        {
            cout << " [" << arr[i] << "] ";
        }

    }
};

int main()
{
    Tree a;
    a.Init();
    for (int i = 1; i < 10; i++)
    {
        a.Add(i);
    }
    cout << "前序";
    a.PreTraversal(1);
    cout <<endl;
    cout << "中序";
    a.MidTraversal(1);
    cout << endl;
    cout << "后序";
    a.LastTraversal(1);
    cout << endl;
    cout << "层序";
    a.LayelTraversal(1);
    return 0;
}
View Code

链表实现:

#include <iostream>
using namespace std;
/////////////////////////////////////////////////////////////////////////////队列
struct Queue
{
    int arr[1024];
    int maxlen;
    int left;//队列尾
    int right;//队列头
    int len;
    
    void Init()
    {
        maxlen = 5;
        left = 0;
        right = -1;
        len = 0;
    }
    bool IsNull()
    {
        if (len==0)return true;
        return false;
    }
    bool IsFull()
    {
        if (len == maxlen)return true;
        return false;
    }
    bool Enqueque(int num)
    {
        bool rt=false;
        if (!IsFull())//一定不能满
        {
            right++;
            arr[right%maxlen] = num;
            len++;
            rt = true;
        }
        return rt;
    }

    int Dequeque()
    {
        int rt = 0x7fffffff;
        if (!IsNull())//一定不能是空的
        {
            
            rt = arr[left % maxlen];
            len--;
            left++;
        }
        return rt;
    }
    void Show()
    {
        for (int i=0; i < len  ; i++)
        {
            cout<< arr[(left+i)%maxlen]<< " ";
        }
        cout << endl;
    }
};
////////////////////////////////////////////////////////////////////////////
struct Node {

    Node* L;
    Node* R;
    int value;
};
struct Tree {
    Node* root;
    int high;
    int lastIndex;//用来插入的时候定位

    void Init()
    {
        root = NULL;
        high = 0;
        lastIndex = 0;
    }
    void Add(int num)
    {
        if (root == NULL)//如此简单就将一个根节点插入了进来
        {
            root = (Node*)malloc(sizeof(Node));
            root->value = num;
            root->L = NULL;
            root->R = NULL;
            lastIndex = 1;
        }
        else
        {//分两步,1计算结点插入的位置,2插入结点
            //利用高度,得出批段,
            //将lastindex- (2^high-1)可以算出该层的位置,
            //然后根据2 , 4,8 来确定具体是谁的子树,?怎么实现呢?
            //第一步生成一个数组,.....
            bool* sx;
            sx = (bool*)malloc(sizeof(bool)*high+1);
            int tmp = pow(2, high);//最下一层,一共有多少个
            int pos = lastIndex - (tmp - 1)+1; //最下一层从左往右数,的序号
            
            if (pos > tmp) 
            {//这种情况直接在左斜边插入一个
                high++;
                for (int i = 0; i < high; i++)sx[i] = false;
            }
            else
            {
                int i = 0;
                while (tmp >= 1)
                {
                    tmp /= 2;
                    if (pos <= tmp)
                    {
                        sx[i++] = false;
                        if(pos>tmp)
                        pos -= tmp;
                    }
                    else
                    {
                        sx[i++] = true;
                        if (pos > tmp) 
                        pos -= tmp;
                    }
                }

            }
            //以上这个if else是结合pos和tmp定位到需要添加的地方(直接计算,免去遍历树的过程,提高效率)
            cout << "添加路径:"; for (int i = 0; i < high; i++)cout << sx[i] << " "; cout << endl;//输出路径看看
            Node* newNode = (Node*)malloc(sizeof(Node));
            newNode->value = num;
            newNode->L = NULL;
            newNode->R = NULL;
            lastIndex++;
            Node* n = root;
            //创建新结点

            for (int i = 0; i < high; i++)
            {
                if (sx[i])
                {//R
                    if (i == high - 1 && n->R == NULL)
                    {
                        n->R = newNode;
                    }
                    else
                    {
                        n = n->R;
                    }
                }
                else
                {//L
                    if (i == high - 1 && n->L == NULL)
                    {
                        n->L = newNode;
                    }
                    else
                    {
                        n = n->L;
                    }
                }
            }
            //知道位置了,就直接迭代插入
        }
    }


    void PreTraversal(Node* _root)
    {
        if (_root == NULL)return;
        cout << " ["<<_root->value << "] ";
        if (_root->L != NULL)PreTraversal(_root->L);
        if (_root->R != NULL)PreTraversal(_root->R);
    }
    void MidTraversal(Node* _root)
    {
        if (_root == NULL)return;

        if (_root->L != NULL)MidTraversal(_root->L);
        cout << " [" << _root->value << "] ";
        if (_root->R != NULL)MidTraversal(_root->R);
    }
    void LastTraversal(Node* _root)
    {
        if (_root == NULL)return;

        if (_root->L != NULL)LastTraversal(_root->L);

        if (_root->R != NULL)LastTraversal(_root->R);
        cout << " [" << _root->value << "] ";
    }
    void LayelTraversal()
    {
        Queue q;
        q.Init();
        q.Enqueque((int)root);
        for (int i = 0; i < lastIndex; i++)
        {
            Node* tmp = (Node*)q.Dequeque();
            cout << " ["<< tmp->value <<"] ";
            if (tmp->L != NULL)q.Enqueque((int) tmp->L);
            if (tmp->R != NULL)q.Enqueque((int) tmp->R);
        }
    }
};

int main()
{
    Tree t;
    t.Init();
    for (int i = 1; i <= 9; i++)
    {
        t.Add(i);
    }
    cout << "前序";
    t.PreTraversal(t.root); cout << endl;
    cout << "中序";
    t.MidTraversal(t.root); cout << endl;
    cout << "后序";
    t.LastTraversal(t.root); cout << endl;
    cout << "层序";
    t.LayelTraversal(); cout << endl;
    


    return 0;
}
View Code

 emmm,关于树和森林转换为二叉树的方法。 以后再来补充吧,感觉要把我写二叉结构变成多叉结构。然后再转换为二叉树?然后再把很多二叉树合并成一个二叉树?。。。。有缘再补充吧

猜你喜欢

转载自www.cnblogs.com/coward/p/11229176.html
今日推荐