数据结构6-二叉树(及算法回顾)

一、回顾

顺序表:数组
链式表:

单向链表

双向链表

循环链表

内核链表

栈:

顺序栈

链式栈

队列:

顺序队列、循环队列

链式队列

散列结构:哈希表:

二、树型结构

        1.定义(一对多):

        树:由n个节点组成的有限集有一个根节点;其他节点只有一个前驱节点,但可以有多个后继节点。

        根:无前驱,有后继n=0,空树

                叶子结点(终端结点):有前驱结点、无后继结点

                分支结点(非终端结点):有前驱结点,有后继结点

        度:

                深度:树的层数

                广度:树中最大结点的度就是树的广度

                        结点的度:当前结点的后继结点个数

        二叉树:树的度为二,且左右子树不可交换位置

                      满二叉树:在不增加层数的前提下,无法再增加一个结点

                      满二叉树第K层结点个数:2^(K-1)

                      K层满二叉树结点总个数:2^K-1

                      完全二叉树:在满二叉树的前提下,增加数据只能从上到下、从左至右;

                                                                                删除数据只能从下至上,从右向左。

                                满二叉树->完全二叉树

                                完全二叉树 !-> 满二叉树

        2.遍历

                (广度优先遍历算法)

                前序遍历:根左右

                中序遍历:左根右

                后序遍历:左右根

                (深度优先遍历算法)

                 层遍历:从上到下,从左到右,逐层遍历

        *已知前序+中序才能还原出唯一的二叉树


#include<stdio.h>
#include"tree.h"
#include"queue.h"
#include<stdlib.h>

//正序遍历的结果
char tr[]={"ABDH##IJ###E##CF##G##"};
int ipt;
//创建二叉树
Tree_node *creat_tree()
{
    Data_type d = tr[ipt++];
    if('#'==d)
    {
        return NULL;
    }
    Tree_node *tree = malloc(sizeof(Tree_node));
    if(NULL ==tree)
    {
        printf("fail creat");
        return NULL;
    }
    tree->data = d;
    tree->pl = creat_tree();
    tree->pr = creat_tree();

    return tree;
}

//正序遍历
void tree_for_each1(Tree_node*tree)
{
    if(NULL==tree)
    {
        return;
    }
    printf("%c",tree->data);
    tree_for_each1(tree->pl);
    tree_for_each1(tree->pr);
}

//中序遍历
void tree_for_each2(Tree_node*tree)
{
    if(NULL==tree)
    {
        return;
    }
    tree_for_each2(tree->pl);
    printf("%c",tree->data);
    tree_for_each2(tree->pr);
}

//逆序遍历
void tree_for_each3(Tree_node*tree)
{
    if(NULL==tree)
    {
        return;
    }
    tree_for_each3(tree->pl);
    tree_for_each3(tree->pr);
    printf("%c",tree->data);
}

//节点数
void num_tree_node(Tree_node*tree,int*num)
{
    if(NULL!=tree)
    {
        (*num)++;
        num_tree_node(tree->pl,num);
        num_tree_node(tree->pr,num);
    }
    return ;
}
//销毁
void destroy_tree(Tree_node*tree)
{
    if(NULL==tree)
    {
        return ;
    }
    Tree_node *delt = tree;
    destroy_tree(delt->pl);
    destroy_tree(delt->pr);
    free(delt); 
}

//树的层数
void level_of_tree(Tree_node*tree,int*level)
{
    if(NULL==tree)
    {
        return ;
    }
    (*level)++;
    int mid1 = *level;
    int mid2 = *level;
    level_of_tree(tree->pl,&mid1);
    level_of_tree(tree->pr,&mid2);
    *level = mid2>mid1?mid2:mid1;    
}


void level_for_each(Tree_node*tree)
{
    if(NULL==tree)
    {
        return ;
    }
    Queue *qu=create_queue();
    enter_queue(qu,tree);
     printf("%c",tree->data);
    while(!is_empty_queue(qu))
    {
        if(qu->pfront->pdata->pl)
        {
            enter_queue(qu,qu->pfront->pdata->pl);
            printf("%c",qu->pfront->pdata->pl->data);
        }
        if(qu->pfront->pdata->pr)
        {
            enter_queue(qu,qu->pfront->pdata->pr);
            printf("%c",qu->pfront->pdata->pr->data);
        }
        out_queue(qu,NULL);
    }
    destroy_queue(&qu);
    puts("");
}

三、算法:解决特定问题的求解步骤

如何衡量算法优越
算法的设计

1.正确性.

        语法正确
        合法的输入能得到合理的结果。
        对非法的输入,给出满足要求的规格说明
        对精心选择,甚至习难的测试都能正常运行,结果正确

2.可读性

        便于交流,阅读,理解高内聚 低耦合

3.健壮性

        输入非法数据,能进行相应的处理,而不是产生异常

4.高效率(时间复杂度)

        时间复杂度:数据增长量与处理时间的关系

        时间复杂度的计算规则
                        1,用常数1 取代运行时间中的所有加法常数

                        2、在修改后的运行医数中,只保留最高阶项

                        3、如果最高阶存在且系数不是1,则去除这个项相乘的常/数。

5.低存储(空间复杂度)

四、算法回顾

排序算法:
1. 思想:实现过程
2. 代码
3. 时间复杂度
4. 排序算法的稳定性:对于两个相同的数据,经过排序,两个相同数据的相对位置没有
                                          发生变化,这就是一个稳定的排序算法。

冒泡排序:相邻两两比较,优先排好最大值

for(i=len-1;i>0;--i)
{
    for(j=0;j<i;++j)
    {
        if(a[i]>a[j])
        {
            swap(a[i],a[j]);   
        }
    }
}

                        时间复杂度:O(n^2)
                        稳定性:稳定

选择排序:将待排位置的数据和后续的数据依次进行比较,将小的存放在待排位置,
                       经过一趟,优先排好最小值。

 
                      for(int i = 0; i < len-1; i++)
                      {
                               for (int j = i+1,; j < len; j++)
                               {
                                           if (a[i] > a[j])
                                                 swap(a[i], a[j]);
                                  }
                      }

                    时间复杂度:O(n^2)
                    稳定性:不稳定        

插入排序: 将待排的元素,依次插入到一个有序序列中,确保插入后任然有序。

 
                      for(int i = 0; i < len-1; i++)
                      {
                               for (int j = i+1,; j < len; j++)
                               {
                                           if (a[i] > a[j])
                                                 swap(a[i], a[j]);
                                  }
                      }

                         时间复杂度:O(n^2)
                        稳定性:稳定
                       
快速排序:选定基准值,从两头分别和基准值比较,比基准值大的向后,比基准值小的向前,优先排好基准值。

void Qsort(int *begin, int *end)
{
    int *p = begin;
    int *q = end;
    if(begin >= end)
    {
        return ;
    }
    
    int t = *begin;
    while(p < q)
    {
        while(p < q && *q >= t)
        {
            --q;
        }
        while(p < q && *p <= t)
        {
            ++p;
        }
        swap(p, q);
    }
    
    swap(begin, p);
    Qsort(begin, p - 1);
    Qsort(p + 1, end);
 
}

                      时间复杂度:O(nlogn)             
                      稳定性:不稳定

希尔排序:将待排的序列,按照增量分成若干个子系列,对子序列进行插入排序。

void shell_sort(int *a, int len)
{
    int j = 0;
    for (int inc = len/2; inc > 0; inc /=2)
    {
        for (int i = inc; i < len; i++)
        {
            j = i;
            int tmp = a[i];
            while (j >= inc && a[j-inc] > tmp)
            {
                a[j] = a[j-inc];
                j = j-inc;
            }
            a[j] = tmp;
        }
    }
}


                       时间复杂度:O(nlogn)-O(n^2) 
                        稳定性:不稳定
二分查找:
                   前提:有序的序列

int BinaryFind(int a[],int len,int n)
 {
     int begin=0;
     int end=len-1;
     int mid;
     while(begin<=end)
     {
         mid=(begin+end)/2;
         if(n<a[mid])
         {
             end=mid-1;
         }
         else if(n>a[mid])
         {
             begin=mid+1;
         }
         else
         {
             break;
         }     }
     if(begin<=end)
     {
         return mid;
     }
     else
     {
         return -1;
     }                                                                       
 
 }

                   时间复杂度:O(logn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值