疯狂/缓慢补数据结构1

串,表,队,栈,KMP。

二叉树,遍历,哈夫曼。

图,DFS,BFS。

最短路径,最小生成树,拓扑排序。

树表的查找,散列表的查找。

线性表查找

排序,内部,外部。、

next为1加前面后缀个数

(1)二叉树性质

1.节点总数为叶子加度为2加度为1

2.叶子为度2加1

(1)基本知识

1.储存结构

【1】邻接矩阵

一个二维数组,连通就记为1.

【2】邻接表

对于每个节点,把相邻的节点接成一个表。

(2)遍历

1,深度优先

2,广度优先

(3)应用

1.普利姆

先随便挑一个点,然后找一下最短的路,把目的计入集合。然后再次对集合进行相同操作,找过的点记为无限大。n方

2.克鲁斯卡尔

先记下一个边的状态数组,a[x]=x;表示他们都不联通,如果联通了就把顶点改成一样的。

记下边的信息,9=(权,顶点),然后排列好,从开头检查边是否联通,没联通就改成联通,要不就跳过。

一般求稀疏,时间为elog2e

3.迪杰斯特拉

从一个原点开始,检测他到周围点的路程,并标在点上。然后选取距离最短的那个点,检测他周围的点的距离,并把从原点经过他到周围点的总路程记录在周围的点上,然后选取联通线路旁最近的点,以此类推。n方

(4)拓扑排序

1.AOV网

输出没有前驱的点,然后在图里删除他,不断这么循环

如果还剩点,那就是图中有环。

2AOE网

最短时间是最长路径长度,叫关键路径,关键路径上的所有活动都是关键活动,最早开始时间是最长路径,

查找。

(1)分块查找

(2)二叉排序树

每个节点的左面都比他小,右面都比他大。

找的时候比他小去左面,比他大去右面。

1插入:存在了的话就不插了

先把这个值的孩子赋为空。

如果向下没有了的话,比上一个小就插到左面,大就插到右面。

如果有的话递归调用自己,大就接右面的,小就接左面的。

2删除:叶子就直接删除

缺个子树的就上移子树

要不就用他的左子树的最右下子树替换。

3.平衡二叉树

平衡因子是左右子树的深度之差,绝对值大于2就不平衡

左左:中间当轴右旋。

左右:把中间按下去的左旋,然后中间当轴的右旋。

右边相反。

(3)散列表

最常见是项数除一个数然后取余。

处理冲突的方法:

1.尝试从1开始不断加数再取余,或加上增量的平方取余。

2.用链表,直接插入。

一.内部排序

(1)插入排序

1.直接插入排序

就是读的时候直接比较然后插入。下面是从小到大排列,函数传入一个头部为空的顺序表。

从后面开始,比一个移一位。

#include<stdio.h>
void b(int lenth,int *a);
int main (void)
{
    int a[6]={0,2,3,6,5,4};int cou1=0;
    b(6,a);
    for(cou1=0;cou1<6;cou1++)
        printf("%d",a[cou1]);
    return 0;
}
void b(int lenth,int *a)
{
    int cou1=0,cou2=0;
    for(cou1=2;cou1<lenth;cou1++)//从2开始
    {
        if(a[cou1-1]>a[cou1])//如果他的上一个大于他的话
        {
            a[0]=a[cou1];//在0存下他
            for(cou2=cou1;a[0]<a[cou2-1];cou2--)//当他小于他的下一个时,把他的下一个移后一位。
            {
                a[cou2]=a[cou2-1];
            }
            a[cou2]=a[0];
        }
    }
}

  稳定,时间o(n方),空间o(1)。

2.折半插入排序

就是把插入排序的顺序查找部分改为2分法查找。

#include<stdio.h>
void b(int lenth,int *a);
int main (void)
{
    int a[6]={0,2,3,6,5,4};int cou1=0;
    b(6,a);
    for(cou1=0;cou1<6;cou1++)
        printf("%d",a[cou1]);
    return 0;
}
void b(int lenth,int *a)
{
    int cou1=0,cou2=0;
    int low,high,m;
    for(cou1=2;cou1<lenth;cou1++)//这是从小到大
    {
        if(a[cou1-1]>a[cou1])
        {
            a[0]=a[cou1];
             low=1;high=cou1-1;//确定查找范围
            while(low<=high)//不断缩小范围直到下限大于上限,说明a[m]大于他而a[m-1]小于他。
            {
                m=(low+high)/2;//m为向下取整,所以是前面表的表尾,在从小到大排中,为小表表尾,如果大了则上限取小表倒数第二项,因为m比过了。如果小了则下线取大表第一个,为m+1;
                if(a[0]<a[m])//这个元素比他大,就把上限减一半再减一
                    high=m-1;
                else
                    low=m+1;//要不就提高下限
            }
                 //最后一次一定是high大于他,low小于她,然后由于惯性他们互换。 for(cou2=cou1-1;cou2>=low;--cou2)//最后low为插入位置 a[cou2+1]=a[cou2]; a[low]=a[0]; } }

  稳定,时间n方,空间1;

  3希尔排序

选个间隔数,把数据分为多组,分别使用插入排序。然后选更小的间隔分组,插入排序。最后取间隔为1;

不稳定。

(2)交换排序

1.冒泡排序

稳定,为n方。

2.快速排序。

随便选个数,然后比他小的放左边,比他大的放右边,对两个新表递归重复这一过程。

 不稳定,时间最好nlog2n,最坏n方。空间最好log2n,最坏n。

(3)选择排序

1。树形选择排序

兄弟之间两两比较,胜者的兄弟之间再两两比较。最后选出第一名,然后把第一名赋最差的值,重复这过程选第二名。

2.堆排序

堆是二叉树线性化,第个i值的父节点为(i – 1) / 2,它的左右子结点下标分别为2 * i + 1和2 * i + 2。

这样就把一个数列转化为多个子数列。然后对子数列进行选择排序。

插入:把元素插入到数组最后一项,然后对他所在的数列进行选择排序。

删除:只能删除第一个。就是把这个整个数列最末尾的数放到第一个的位置上,然后进行选择排序。要判断节点的子节点哪个是最好的,然后与他交换。

堆化数组:叶子节点不用排,所以我们要从最后一个不是叶子节点的节点(n/2向小取整)开始向上直到0的堆排序。

不稳定,最坏nlog2n。1

(3)归并排序

有点像逆希尔。就是将数列的元素分为越来越大的有序表。

两个表合并是申请一个两个表那么大的数组,然后在两个数组里选着往里放。

传入左右端点low,high

(如果表的low等于high,返回)

求出中间值

对右表递归

对左表递归

合并两个表

稳定,nlog2n。n.

猜你喜欢

转载自www.cnblogs.com/pornhub/p/9245418.html