数据结构

寒假自学了一点数据结构,最近又看了《挑战2》来复习了以下基本的数据结构,以此随笔简单记录之。

数据结构

Intro
数据结构是计算机中存储,组织数据的方式,通常来说,它并不是单指数据集合本身,而是包含以下内容:

  1. 数据集合,如数组,结构体等。
  2. 操作,比如栈有压栈,弹出等操作。
  3. 规则,规定了某种数据结构下在操作数据集合时应该遵守的规则,如栈的 Last In First Out.

链表

Intro
在很多情况下我们经常需要动态地操作数据集合,这时需要根据需要开辟或者释放内存空间,而有时我们要在任意位置插入新数据,在这些情况下,使用数组是非常不方便的,我们需要使用链表来管理数据集合。链表中相邻的节点不像数组那样分布在相邻的空间中,而是可能离散地分布。其中每个节点包含两个信息,本节点的值和指向下一个节点的指针(如果是双链表则还有指向上一个节点的指针), 下面我们用两种方法来模拟链表,一种是使用数组,这种方法还是需要估计空间,但是速度更快,另一种是使用结构体,这种方法不需要估计空间,新建节点时开辟即可,但是速度相对较慢。

单链表

链表中最简单的是单向链表。单向链表包含信息域和指针域。

下面主要介绍用数组模拟的方法,用结构体模拟的方法可以类似得到。

代码和解释

//head表示头节点的下标
//e[i]表示节点[i]的值
//ne[i]表示节点[i]的next指针
//idx存储当前已经用到了哪个点
int e[N],ne[N],idx,head;
//链表的初始化(-1表示空节点)
void initialize(){
    head=-1;
    idx=0;
}
//头部插入
void add_head(int x){
    e[idx]=x;
    ne[idx]=head;
    head=idx;
    idx++;
}
//在第k个插入的数后面插入
void insert(int k,int x){
    e[idx]=x;
    ne[idx]=ne[k-1];
    ne[k-1]=idx;
    idx++;
}
//删除第k个插入的数后面的数
void remove(int k){
    if(k==0){
        head=ne[head];
    }
    else{
        ne[k-1]=ne[ne[k-1]];
    }
}

双链表

双链表较单链表稍复杂一些,它的指针域包含 next 和 prev 指针,下面是数组模拟的代码和解释。

代码和解释

//r[]用来存储next指针,l[]存储prev指针,e[]存储节点的值,idx表示当前用到哪个节点
int r[N],l[N],e[N],idx;
//初始化,0表示头节点,1表示尾节点,idx从2开始
void init(){
    r[0] = 1;
    l[1] = 0;
    idx = 2;
}
//在idx为k的点右边插入一个点
void insert(int k,int x){
    e[idx] = x;
    r[idx] = r[k];
    l[r[k]] = idx;
    l[idx] = k;
    r[k] = idx;
    idx++;
}
//删除第k个插入的点
void Delete(int k){
    r[l[k+1]] = r[k+1];
    l[r[k+1]] = l[k+1];
}
/*
L x,表示在链表的最左端插入数 x。
R x,表示在链表的最右端插入数 x。
D k,表示将第 k 个插入的数删除。
IL k x,表示在第 k 个插入的数左侧插入一个数。
IR k x,表示在第 k 个插入的数右侧插入一个数。
*/

链表的应用

用的比较多的是单链表,用来存储图。插入都是 O(1)的,而查找是O(n)的。

Intro
栈是一种能有效帮助我们临时保存数据的数据结构,遵循 Last In First Out 的规则,支持 push(插入),pop(弹出),top(栈顶元素),isEmpty(是否为空)等操作。
用数组模拟栈是十分简单的,只需要开辟一个适当大小的数组,然后借助一个栈指针。

代码和解释

//top 是栈指针,指向栈顶元素,栈为空时置为0
int stk[N],top = 0;

void push(int x){
    stk[++top] = x;
}

void pop(){
    if(top)
        top--;
}

bool isEmpty(){
    return top == 0;
}

int Top(){
    return stk[top];
}

应用

[https://www.acwing.com/problem/content/description/3305/](Acwing 3302.表达式求值)
[https://www.acwing.com/problem/content/832/](Acwing 830.单调栈)

队列

队列是一种特殊的线性表,遵循规则 First in First out, 正如生活中常见的那样。

模拟队列主要依靠两个模拟指针,分别指向队头和队尾。

代码和解释

// head 为队头指针,指向队头,tail为队尾指针,指向最后一个元素的后一个位置。
int q[N],head = 0,tail = 0;

void push(int x){
    q[tail++] = x;
}

void pop(){
    head++;
}

bool isempty(){
    return head == tail;
}

int front(){
    return q[head];
}

posted @ 2021-04-29 14:49  今天AC了吗  阅读(95)  评论(0)    收藏  举报