考研数据结构汇总

仅供参考!!!

必背知识点

数据结构 是相互之间存在一种或多种特定关系的数据元素的集合

数据结构的三要素:

逻辑结构,存储结构,数据的运算(定义(逻辑结构的,运算的功能)和实现(物理结构的,运算的具体操作步骤))

逻辑结构:数据元素之间的逻辑关系,与数据的存储无关,独立于计算机,线性结构和非线性结构

存储结构:数据结构在计算机中的表示

顺序存储:逻辑上相邻,物理上也相邻

链式存储:逻辑上相邻,物理上可以不相邻

索引表:在存储信息时,还需要建立附加的索引表

哈希表:根据关键字,直接计算出该元素的存储地址。

算法:对特定问题求解步骤的一种描述

基本特性:有确可叔叔

有穷性:算法在有穷步之后结束,并且每一步都在有穷时间内完成

确定性:算法中每条指令都是有确定含义的,对于同一输入,有同一输出

可行性:算法中描述的操作可以根据现有实现的基本运算执行有限次后完成

输入:一个或多个输入

输出:一个或多个输出,这些输出和输入有着某种关系

好的算法:正可健效

正确性:算法能正确的求解问题

可读性:算法应该有良好的可读性

健壮性:输入非法数据是,可以对这些错误操作进行处理

效率和低存储需求:执行时间和所需最大空间内存

时间复杂度:一个算法所需花费的时间,和问题规模n有关

空间复杂度:一个算法在运行过程中临时占用存储空间的大小

线性表:由n个相同数据类型的数据元素的构成的有序序列,逻辑关系,表示一对一的相邻关系

相关操作:求表长,定位元素位置下标,初始化表,表得插入,表得删除,输出表,判断表是否为空

顺序表:线性表的顺序存储,他是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得在逻辑上相邻,物理上也相邻。支持随机访问,存储密度高,创建数组成功后不可再次更改数组大小,插入和删除需要移动大量数组元素。

单链表:线性表的链式存储,一组任意的存储单元来存储线性表中的数据元素。插入和删除的效率较高,没有元素个数的限制,不支持随机存储

双链表:两个指针域,,一个指针域指向其前驱,一个指向其后继节点

循环链表:尾结点指向其头结点

只允许在一段进行插入和删除的线性表,进行插入和删除的一端称栈顶,不进行插入和删除的一段称为栈底。后进先出

栈的基本操作包含:入栈,出栈,判断栈是否为空,是否已满,栈的初始化等

栈的实现:

顺序栈:顺序表的实现,存在溢出的风险,链栈:使用链表实现,不存在溢出的情况

队列是限制操作的线性表,只能在一段删除,一端插入,先进先出

基本操作:入队,出队,判断队满,对空,初始化等

队列的实现:

循环队列:使用顺序表实现,利用取模的方式,从逻辑上看是一个环形

链队:使用链表实现,用两个指针标记队列的头部和尾部,优点是不会存在队列慢的情况

判断队满:牺牲一个元素空间,利用一个标记位

数组由n个相同数据类型的数据元素构成的有序序列,是线性表的推广,一维数组可以看做线性表,二维数组可以将其元素看成定长线性表,下标的取值范围称为维界。

广义表:由0个或者多个,元素或子表组成的有序序列,线性表的推广

两个基本操作:

取表头:广义表中的第一个元素

取表尾:取出广义表中除第一个元素以外的其他元素

是由零个或多个字符组成的有限序列

串的实现:

顺序存储:用一组连续的存储空间依次存储串中的元素,删除和插入需要移动大量的元素

链式存储:用一组非连续的存储空间存储串中的元素,不需要移动大量元素

串的基本操作:串的复制,求串长,求子串,串联接,串的销毁

哈希表:根据关键码值而直接进行访问的数据结构

树是n个结点的有限集,它或为空树; 或为非空树,对于非空树T:
(1)有且仅有一个称之为根的结点;
(2)除根结点以外的其余结点可分为 m个互不相交的有限集 Ti , T2 , …,几,其中每一个集合本身又是一棵树,并且称为根的子树

性质

树中一个结点的孩子个数称为该结点的度。

  1. 树中结点n的个数:n = n0+n1+n2+…+1
    

在这里插入图片描述

二叉树

是n个结点所构成的集合,它或为空树(n= 0); 或为非空树,
对于非空树T:
(1) 有且仅有一个称之为根的结点;
(2)除根结点以外的其余结点分为两个互不相交的子集T1和T2, 分别称为T的左子树和右子树且T1和T2本身又都是二叉树

满二叉树:深度为 K 且含有 2^k-1个结点的二叉树

完全二叉树:深度为K的, 有n个结点的二叉树, 当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时, 称之为完全二叉树

先序,中序后序,中序遍历可以得到唯一一个二叉树

二叉树的遍历:按照某条搜索路径访问树中每个节点,使得每个节点都被访问依次且仅被访问一次

二叉排序树:根节点的左边元素均小于根节点,右边均大于根节点,其左右孩子也满足这一条件

性质

  1. 对任何一棵二叉树T, 如果其终端结点数为n0,度为2的结点数为n2,则n0 = n2+1

  2. 非空二叉树上第K层至多有2^(k-1)个结点

  3. 高度/深度为h的二叉树至多有2^h-1 个结点,至少2^(h-1)个结点

  4. 在这里插入图片描述

  5. 具有 n 个结点的完全二叉树的深度/高度在这里插入图片描述

  6. n个结点的二叉树采用链式存储,其中空指针为 n+1

平衡二叉树的插入

为了避免树的高度增长过快,影响二叉排序树的性能,在二叉树进行插入和删除时,需要确保左子树的高度减去右子树的高度只差小于等于一

LL:结点A左孩子的左结点上插入结点。todo:右旋,A左孩子的右子树为A的左孩子

在这里插入图片描述

RR:结点A右孩子的右结点上插入结点。todo:左旋,A右孩子的左孩子为A的右孩子

在这里插入图片描述

LR:结点A左孩子的右孩子上插入结点。todo:先左旋转后右旋转,插入点为C,C的左孩子为B,右孩子为A。C的左孩子放到调整后结点的左边下,右孩子放到右边。

在这里插入图片描述

RL:结点A右孩子的左孩子上插入结点。todo:先右旋后左旋,插入点为C,C的左孩子为A,右孩子为B。C的左孩子放到调整后结点的左边下,右孩子放到右边。

在这里插入图片描述

哈夫曼树

带路径长度最小的二叉树即为哈夫曼树

带权路径长度:从树的根到任意结点的经过边数与该结点上权值的乘积。

树中所有结点的带权路径长度之和称为该树的带权路径长度WPL。

在这里插入图片描述
在这里插入图片描述

哈夫曼树中不存在度为1的结点

n个叶子结点的哈夫曼树总结点数2n-1

图 G由两个集合V和E组成,记为G=(V,E),其中V是顶点的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对称为边。V(G)和E(G)通常分别表示图G的顶点集合和边集合,E(G)可以为空集。若E(G)为空,则图G只有顶点而没有边。
对于图G,若边集E( G)为有向边的集合,则称该图为有向图;

若边集E( G)为无向边的集合,则称该图为无向图。

完全图:全图中任意两个顶点之间都存在边 ,共n(n-1)/2条边

n个顶点的有向完全图有n(n-1)条边

搜索性能分析

邻接表:o(v+e)

邻接矩阵:o(v^2)

关键路径

源点到汇点的最长路径

关键活动:边上的权值增加,将导致关键路径变化的活动

最早发生时间:v1-vk的最长路径长度

最迟发生时间:总时间-(vk-vj的路径长度)

最早开始时间:最早发生时间

最晚开始时间:总时间 -(vk-vj的路径长度) - vk完成所需时间

最短路径:带权路径长度最短的那条路径

拓扑序列:由 一个有向无环图的顶点组成的序列

满足:

​ 一个顶点只出现一次

​ 顶点a在顶点b之前,则不存在由顶点b到顶点a的边

算法步骤:

​ 选择一个没有前驱的顶点输出

​ 删除改顶点和所有以它为起点的有向边

​ 重复上述过程直至当前网中不存在无前驱的顶点为止

排序

名称方式存储空间时间稳定性
直接插入将数组分为三部分,已排序区,待排序元素,待排序区,每一次将待排元素和已排序区的元素进行比较,待排元素放到数组0的位置,如果大于之前的元素位置为i,已排序区整体后移一位,将待排元素插入,以此往复比较n-1次顺序链式1n2稳定
折半插入再插入排序的基础上,增加了查找的效率,其他点不变顺序1n2稳定
希尔排序缩小增量排序,增量分组,每一个分组都是插入排序,每一次的增量为上一次增量的一半,一趟就是增量的比较次数顺序不稳定
冒泡排序将i个元素和i-1个元素进行比较,如果发现i-1个元素大于第i个元素,则交换二者位置,每一趟排序都有一个元素再最终位置上。顺序链式1n2稳定
快速排序根据一个枢纽,从后往前找出小于枢纽的值,放到low处,从前往后找出第一个大于枢纽的值,将第high处,以此往返直至low==high,将枢纽值放到low处,完成一趟排序顺序lognnlog2n不稳定
选择排序将数组分为已排序区和待排序区,每一趟都是从n-i+1个元素中选择一个最小的元素和当前第i个元素进行互换,一趟确定一个最终位置顺序链式1n2不稳定
归并排序将两个或两个以上的有序表组合成一个新的有序表顺序nnlog2n稳定
堆排序从小根堆或者大根堆中选择根节点然后和末尾元素互换位置,将末尾位置输出,最好对树继续调整链式1nlog2n不稳定

数据压缩

  1. 对称矩阵:存放数组大小n(n+1)/2
    1. 下三角(含主对角线):i(i-1)/2+j-1
    2. 上三角:j(j-1)/2+i-1
  2. 稀疏矩阵:三元组

ASL

顺序表

成功:n+1/2

失败:n

二叉树

成功:(每层结点数*高度)之和/总结点数

失败:(空余结点数*空结点父节点高度)之和/总结点数+1

散列表

成功:探测次数之和/数据总数

失败:比较次数(后续结点为空比较失败)之和/数据总数+1

线索二叉树

若无左子树,则将左指针指向其前驱结点;
若无右子树,则将右指针指向其后继结点。

贪心算法:只寻求局部最优解,不从整体出发,得到的最终结果可能不是最优解,从上往下,一步一步得到结果
动态规划:将一个大问题分为若干个子问题,这些子问题可能重复,为防止记录重复,可以将它们记录下来,从下往上,且前一个子问题对后一个子问题必然产生影响,最终一步一步地到最优解。
分治法:将一个大问题分成若干个子问题,使用递归求解,子问题之前相互独立,子问题最终的解的合集就为最优解。

查找:在数据集合中,找出满足某种条件的数据元s素的过程。

查找表:用于查找数据的集合

关键字:数据元素中唯一标识该数据项的值

平均查找长度:一次查找需要比较关键字的次数

顺序表

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct
{
    int *arr;
    int max, len;
} Sqlist;

void InitList(Sqlist *list)
{
    int x, i;
    printf("input max:");
    scanf("%d", &x);
    list->arr = (int *)malloc(sizeof(int) * x);
    list->len = 0;
    list->max = x;
}
int Length(Sqlist list)
{
    return list.len;
}
int LocateElem(Sqlist list, int e)
{
    int res = -1;
    for (int i = 0; i < list.len; i++)
    {
        if (e == list.arr[i])
        {
            res = i + 1;
            break;
        }
    }
    return res;
}
int GetElem(Sqlist list, int i)
{
    return list.arr[i - 15];
}
bool ListInsert(Sqlist *list, int i, int e)
{
    if (i < 1 || i > list->len + 1 || list->len == list->max)
    {
        return false;
    }
    for (int j = list->len; j >= i; j--)
    {
        list->arr[j] = list->arr[j - 1];
    }
    list->arr[i - 1] = e;
    list->len++;
    return true;
}
bool ListDelete(Sqlist *list, int i, int *e)
{
    if (i < 1 || i > list->len)
    {
        return false;
    }
    e = &list->arr[i - 1];
    for (int j = i; j < list->len; j++)
    {
        list->arr[j - 1] = list->arr[j];
    }
    list->len--;
    return true;
}
void PrintList(Sqlist list)
{
    for (int i = 0; i < list.len; i++)
    {
        printf("%d ", list.arr[i]);
    }
    putchar('\n');
}
bool Empty(Sqlist list)
{
    if (list.len == 0)
    {
        return true;
    }
    return false;
}
void DestoryList(Sqlist *list)
{
    free(list->arr);
    list->arr = NULL;
    list->len = 0;
    list->max = 0;
}
void main()
{
    Sqlist list;
    int x;
    InitList(&list);
    for (int i = 0; i < 4; i++)
    {
        list.arr[i] = i;
    }
    list.len = 4;
    PrintList(list);
    printf("pos:%d\n", LocateElem(list, 1));
    printf("ele:%d\n", GetElem(list, 2));
    printf("len:%d\n", Length(list));
    ListInsert(&list, 2, 333);
    PrintList(list);
    ListDelete(&list, 1, &x);
    PrintList(list);
    DestoryList(&list);
}	

链表

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct LNode
{
    int Data;
    struct LNode *next;
} LNode, *linkList;

linkList HeadInsert(linkList list)
{
    int x, i;
    LNode *s;
    printf("input len:");
    scanf("%d", &x);

    list = (LNode *)malloc(sizeof(LNode));
    list->next = NULL;
    for (i = 0; i < x; i++)
    {
        s = (LNode *)malloc(sizeof(LNode));
        s->Data = i + 1;
        s->next = list->next;
        list->next = s;
    }
    return list;
}

linkList tailInsert(linkList list)
{
    int x, i;
    LNode *s, *h;
    printf("input len:");
    scanf("%d", &x);
    h = list = (LNode *)malloc(sizeof(LNode));
    for (i = 0; i < x; i++)
    {
        s = (LNode *)malloc(sizeof(LNode));
        s->Data = i + 1;
        s->next = NULL;
        list->next = s;
        list = s;
    }
    return h;
}
LNode *Getelem(linkList list, int i)
{
    LNode *s;
    int j = 1;
    list = list->next;
    while (list && i > 0)
    {
        if (i == j)
        {
            break;
        }
        j++;
        list = list->next;
    }
    return list;
}
LNode *LocateElem(linkList list, int e)
{
    LNode *s = list->next;
    while (s)
    {
        if (e == s->Data)
        {
            break;
        }
        s = s->next;
    }
    return s;
}
void printNode(linkList list)
{
    list = list->next;
    while (list)
    {
        printf("%d ", list->Data);
        list = list->next;
    }
    putchar('\n');
}
void InsertNode(linkList list, int i, int e)
{
    LNode *s, *p = Getelem(list, i - 1);
    s->next = p->next;
    p->next = s;
    s->Data = e;
}
void deleteNode(linkList list, int i)
{
    LNode *s, *p, *f;
    p = Getelem(list, i - 1);
    f = p->next;
    p->next = f->next;
    free(f);
}
int len(linkList list)
{
    int i = 0;
    list = list->next;
    while (list)
    {
        i++;
        list = list->next;
    }
    return i;
}

void main()
{
    LNode *p, *s;
    p = HeadInsert(p);
    printNode(p);
    s = tailInsert(s);
    printNode(s);

    deleteNode(s, 2);
    printNode(s);

    // InsertNode(p, 1, 4);
    // printNode(p);

    printf("%d ", len(s));
}	

顺序栈

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define maxsize 10

typedef struct
{
    int top;
    int list[maxsize];
} stack;

stack *initStack()
{
    stack *s = (stack *)malloc(sizeof(stack));
    s->top = -1;
    for (int i = 0; i < maxsize; i++)
    {
        s->list[i] = 0;
    }
    return s;
}

bool enStack(stack *s, int e)
{
    if ((s->top + 1) == maxsize)
    {
        return false;
    }
    s->list[++(s->top)] = e;
    printf("e:%d\n", s->list[s->top]);
    return true;
}
bool popStack(stack *s, int *x)
{

    if (s->top - 1 == -2)
    {
        return false;
    }

    *x = s->list[s->top--];
    printf("x:%d\n", *x);
    return true;
}
bool empty(stack *s)
{
    if (s->top == -1)
    {
        return true;
    }
    return false;
}

void main()
{
    stack *s;
    int x;
    s = initStack();

    enStack(s, 1);
    enStack(s, 2);

    popStack(s, &x);

    popStack(s, &x);

    if (empty(s))
    {
        printf("true");
    }
}	

链栈(带头结点)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct node
{
    int data;
    struct node *next;
} stack;

stack *initStack()
{
    stack *s = (stack *)malloc(sizeof(stack));
    s->next = NULL;
    return s;
}

bool enStack(stack *s, int e)
{
    stack *node = (stack *)malloc(sizeof(stack));
    node->data = e;
    node->next = s->next;
    s->next = node;
    return true;
}
bool popStack(stack *s, int *x)
{
    stack *p = s->next;
    s->next = p->next;
    printf("%d\n", p->data);
    free(p);
    return true;
}
bool empty(stack *s)
{
    if (s->next == NULL)
    {
        return true;
    }

    return false;
}

void main()
{
    stack *s;
    int x;
    s = initStack();

    enStack(s, 1);
    enStack(s, 2);

    popStack(s, &x);

    popStack(s, &x);

    if (empty(s))
    {
        printf("true");
    }
}

队列

#include <stdio.h>//顺序队
#include <stdlib.h>
#include <stdbool.h>

#define maxsize 10

typedef struct
{
    int data[maxsize];
    int front, rear;
} Squeue;

Squeue *initQueue()
{
    Squeue *s = (Squeue *)malloc(sizeof(Squeue));
    s->front = s->rear = 0;
    return s;
}
bool empty(Squeue *s)
{
    if (s->front == s->rear)
    {
        return true;
    }
    return false;
}

bool enQueue(Squeue *s, int e)
{
    if (s->front == (s->rear + 1) % maxsize)
    {
        return false;
    }
    s->data[s->rear] = e;
    printf("%d ", s->data[s->rear]);
    s->rear = (s->rear + 1) % maxsize;
    return true;
}
bool popQueue(Squeue *s)
{
    if (empty(s))
    {
        return false;
    }
    printf("%d ", s->data[s->front]);
    s->front = (s->front + 1) % maxsize;
    return true;
}

void main()
{
    Squeue *s;
    int x;
    s = initQueue();

    for (int i = 0; i < maxsize - 2; i++)
    {
        enQueue(s, i);
    }
    putchar('\n');
    if (enQueue(s, 122))
    {
        printf("true");
    }
}

链队

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define maxsize 10

typedef struct Node
{
    int data;
    struct Node *next;
} Node;

typedef struct
{
    Node *front, *rear;
} Squeue;

Squeue *initQueue(Squeue *s)
{
    s->front = s->rear = (Node *)malloc(sizeof(Node)); //头结点
    s->front->next = NULL;
    return s;
}
bool empty(Squeue *s)
{
    if (s->front == s->rear)
    {
        return true;
    }
    return false;
}

void enQueue(Squeue *s, int e)
{
    Node *q = (Node *)malloc(sizeof(Node));
    q->data = e;
    q->next = NULL;
    s->rear->next = q;
    s->rear = q;
}
bool popQueue(Squeue *s, int *x)
{
    if (empty(s))
    {
        return false;
    }
    Node *q = s->front->next;
    *x = q->data;
    s->front->next = q->next;
    if (q == s->rear)
    {
        s->rear = s->front;
    }
    free(q);
    return true;
}

void main()
{
    Squeue *s;
    int x;
    s = initQueue(s);

    for (int i = 0; i < maxsize; i++)
    {
        enQueue(s, i);
    }
    putchar('\n');
    popQueue(s, &x);
    printf("%d ", x);
    popQueue(s, &x);
    printf("%d ", x);
    popQueue(s, &x);
    printf("%d ", x);
}

括号配对

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define maxsize 10
typedef struct
{
    char data[maxsize];
    int top;
} stack;
stack *InitStack(stack *s)
{
    s = (stack *)malloc(sizeof(stack));
    s->top = -1;
    return s;
}
bool stackEmpty(stack *s)
{
    if (s->top == -1)
    {
        return true;
    }
    return false;
}
bool Push(stack *s, char e)
{
    if (s->top + 1 == maxsize)
    {
        return false;
    }
    s->data[++(s->top)] = e;
    return true;
}
bool Pop(stack *s, char *e)
{
    if (stackEmpty(s))
    {
        return false;
    }
    *e = s->data[s->top--];

    return true;
}
bool brecketCheck(char str[], int len)
{
    stack *s;
    char tmp;
    s = InitStack(s);
    if (len % 2 != 0)
    {
        return false;
    }

    for (int i = 0; i < len; i++)
    {
        if (str[i] == '(' || str[i] == '{' || str[i] == '[')
        {
            Push(s, str[i]);
        }
        else
        {
            if (stackEmpty(s))
            {
                return false;
            }
            Pop(s, &tmp);
            printf("%c : %c \n", tmp, str[i]);
            if ((str[i] == '}' && tmp != '{') || (str[i] == ']' && tmp != '[') || (str[i] == ')' && tmp != '('))
            {
                return false;
            }
        }
    }
    return stackEmpty(s);
}
void main()
{
    char data[maxsize];
    data[0] = '(';
    data[1] = '{';
    data[2] = '[';
    data[3] = ']';
    data[4] = '}';
    data[5] = ']';
    if (brecketCheck(data, 6))
    {
        printf("true");
    }
    else
    {
        printf("false");
    };
}
  • 17
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值