基础数据结构

发布时间:2024年01月07日

1. 单链表

#include<iostream>

using namespace std;
const int N = 1e5 + 10;

int n;
// 分别存储当前节点的值,当前节点下一个节点的值,头结点,id号
int value[N], nepoint[N], head, idx;

void init(){
    head = -1;
    idx = 0;
    
}

// 1.H 将某个x插入到头结点上
void int_to_head(int x){
    value[idx] = x;// 初始化节点的值
    nepoint[idx] = head;// 初始化头结点的下一个节点,头插法
    head = idx;// 改变头结点
    idx++;
    
}

// 2.删除
void remove(int k){
    nepoint[k] = nepoint[nepoint[k]];
}


// 3.添加
void add(int k, int x){
    value[idx] = x;
    nepoint[idx] = nepoint[k];
    nepoint[k] = idx;
    idx++;
}
int main(){
    cin >> n;
    init();//初始化链表
    for (int i = 0; i < n; i++) {
        char s;
        cin >> s;
        if (s == 'H'){
            int x;
            cin >> x;
            int_to_head(x);
        }
        if (s == 'D'){
            int k;
            cin >> k;
            if (k == 0) head = nepoint[head];
            else remove(k - 1);
        }
        if (s == 'I'){
            int k, x;
            cin >> k >> x;
            add(k - 1, x);// 找到 k 的前一个元素,利用它进行插入
        }
    }
    for (int i = head; i != -1; i = nepoint[i]){
        cout << value[i] << ' ';
    }
    return 0;
}

2. 双链表

#include<iostream>
using namespace std;
const int N = 1e5+10;

int e[N], l[N], r[N];

int m, idx;

void init(){
    r[0] = 1;
    l[1] = 0;
    // 1.idx 从 2 开始。我们插入的第i个数的idx为i+1
    idx = 2;
}

// 在第k个插入的数右边插入x
void add(int k, int x){
    e[idx] = x;
    r[idx] = r[k];
    l[idx] = k;
    l[r[k]] = idx;
    r[k] = idx;
    // 2.要让idx++
    idx++;
}

void remove(int k){
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}


int main(){
    cin >> m;
    init();
    while(m--){
        string op;
        cin >> op;
        int k, x;
        if (op == "R"){
            cin >> x;
            // 在尾节点左边的一个节点的右边插入
            add(l[1], x);
        }else if (op == "L"){
            cin >> x;
            // 在头结点的右边插入
            add(0, x);
        }else if (op == "D"){
            cin >> k;
            // k 和 k + 1 的对应关系
            remove(k + 1);
        }else if (op == "IL"){
            cin >> k >> x;
            add(l[k + 1], x);
        }else{
            cin >> k >> x;
            add(k + 1, x);
        }
    }
    // 3.注意!头结点不用输出,所以第一个输出的是r[0]
    // 尾节点也不用输出
    // 不断推进
    for (int i = r[0]; i != 1; i = r[i]){
        cout << e[i] << " ";
    }

}

3. 模拟栈

#include<iostream>
using namespace std;

const int N = 1e5 + 10;
int top = -1;// 栈顶元素为空
int v[N];

int main(){
    int n;
    cin >> n;
    while(n--){
        string s;
        cin >> s;
        if (s == "push")
        {
            int a;
            cin >> a;
            v[++top] = a;// 更新栈顶元素
        }
        if (s == "pop")
        {
            top--;// 移动栈顶指针
        }
        if (s == "query")
        {
            cout << v[top] << endl;
        }
        if (s == "empty")
        {
            cout << (top == -1 ? "YES" : "NO") << endl;
        }
    }
}

4. 模拟队列

#include<iostream>
using namespace std;
const int N = 1e5+10;
int q[N];

int main(){
    int n;
    cin >> n;
    int h = 0, t = -1;
    while(n--){
        string op;
        cin >> op;
        int x;
        if (op == "push"){
            cin >> x;
            q[++t] = x;
        }else if (op == "pop"){
            h++;
        }else if (op == "empty"){
            if (h <= t) puts("NO");
            else puts("YES");
        }else {
            cout << q[h] << endl;
        }
    }
}

5. 单调栈

#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int stk[N], t;

int main(){
    int n;
    cin >> n;
    while(n--){
        int x;
        scanf("%d", &x);

        // 如果栈非空,检查其中是否有 >= x 的元素,如果有要清空
        while(t && stk[t] >= x) t--;
        // 如果栈是空的,打印 -1
        if (!t) cout << -1 << ' ';
        // 如果栈是非空的,打印栈顶元素
        else cout << stk[t] << " ";
        // 将新来的元素加入栈
        stk[++t] = x;
    }
    return 0;
}

6. 模拟堆

down: 往下调整,

up: 往上调整

插入:heap[s++] = x, up(size)

求最小:heap[1]

删除:swap[heap[1], heap[size]], size--, down[1] 删除头元素很麻烦

删除任意元素:heap[k] = heap[size]; size--; down(k), up(k)

修改元素:heap[k] = x; down(k), up(k)

#include<iostream>
#include<algorithm>
#include<string.h>

using namespace std;

const int N = 1e5 + 10;

int h[N], ph[N], hp[N], cnt;

// ph[1] = a, hp[a] = 1
void heap_swap(int a, int b)
{
    swap(ph[hp[a]], ph[hp[b]]);
    swap(hp[a], hp[b]);
    // 交换堆中存储的 a 和 b 位置的值
    swap(h[a], h[b]);
}

// 对堆中位置在 u 的元素执行
void down(int u)
{
    int t = u;
    if (u*2 <= cnt && h[u*2] < h[t]) t = u*2;
    if (u*2 + 1 <= cnt && h[u*2+1] < h[t]) t = 2*u + 1;
    if (u != t)
    {
        heap_swap(u, t);
        down(t);
    }
}

void up(int u)
{
    while(u/2 && h[u] < h[u/2])
    {
        heap_swap(u, u/2);
        u >>= 1;
    }
}

int main()
{
    int n, m = 0;
    scanf("%d", &n);
    while(n--)
    {
        char op[5];
        int k, x;
        scanf("%s", op);
        if (!strcmp(op, "I"))
        {
            scanf("%d", &x);
            // 更新 size
            cnt++;
            // 唯一 ID 表示当前是第 m 个插入的数
            m++;
            // size 和 ID 建立联系
            ph[m] = cnt, hp[cnt] = m;

            h[cnt] = x;
            up(cnt);
        }
        // h[1] 存储的是最小的元素
        else if (!strcmp(op, "PM")) printf("%d\n", h[1]);
        else if (!strcmp(op, "DM"))
        {
            heap_swap(1, cnt);
            cnt--;
            down(1);
        }
        else if (!strcmp(op, "D"))
        {
            scanf("%d", &k);
            // 找到该数在堆中的位置
            k = ph[k];
            heap_swap(k, cnt);
            cnt--;
            up(k);
            down(k);
        }
        else
        {
            scanf("%d%d", &k, &x);
            k = ph[k];
            h[k] = x;
            up(k);
            down(k);
        }
    }
    return 0;
}

7. 堆排序

从 n/2 开始 down,复杂度为 O(n)

#include<iostream>
#include<algorithm>// 因为需要调用swap
using namespace std;
const int N = 1e5 + 10;

int h[N], Msize;//堆的大小

int n, m;

void down(int u){
    int t = u;
    // 判断左右孩子是否存在以及他们的大小
    // 更新 t 为最小的元素下标
    if(u*2 <= Msize && h[u*2] < h[t]) t = u*2;
    if(u*2 + 1 <= Msize && h[u*2 + 1] < h[t]) t = u*2 + 1;
    if(u != t){
        swap(h[u], h[t]);
        down(t);
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &h[i]);
    Msize = n;
    // 收敛性证明:错位相减
    for(int i = n / 2;i;i--) down(i);
    while(m--){
        cout << h[1] << " ";
        h[1] = h[Msize--];
        down(1);
    }

    return 0;

}

文章来源:https://blog.csdn.net/Algo_x/article/details/135439886
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。