算法总结-数据结构

1,链表

链表可以使用结构体+指针的方式实现,但是这种方式的效率很低
链表中最常用的是邻接表(n个链表),邻接表的作用主要是存储树和图
所以这里分别介绍了使用数组来实现单链表和双链表的方法

单链表

const int N = 1e5 + 10;

//head表示头节点的下标
//e[i]表示节点i的值
//ne[i]表示节点i的next指针是多少
//idx表示当前已经用到了哪个点
int e[N], ne[N], head, idx;

//初始化
void init() {
    head = -1;
    idx = 0;
}

//将x插到头节点后面
void add_to_head(int x) {
    e[idx] = x;
    ne[idx] = head;
    head = idx;
    idx++;
}

//将x插到下标为k的节点后面
void add(int k, int x) {
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx;
    idx++;
}

//将下标为k的节点后面的节点删除
void remove(int k) {
    ne[k] = ne[ne[k]];
}

双链表

const int N = 1e5 + 10;

//e[i]表示下标为i的值
//l[i]表示下标为i的左指针
//r[i]表示下标为i的右指针
//idx表示当前可用的下标
int e[N], l[N], r[N], idx;

//初始化
void init() {
    //0和1分别表示头和尾,0的右边是1,1的左边是0,idx从2开始
    r[0] = 1;
    l[1] = 0;
    idx = 2;
}

//在下标为a的节点右边插入x
void insert(int a, int x) {
    //先设置idx的值,左右指针
    e[idx] = x;
    r[idx] = r[a];
    l[idx] = l[r[a]];
    //然后将a后面的节点的左指针指向idx
    l[r[a]] = idx;
    //将a的右指针指向idx
    r[a] = idx;
    idx++;
}

//删除下标为a的节点
void remove(int a) {
    l[r[a]] = l[a];
    r[l[a]] = r[a];
}

2,栈和队列

因为个人比较喜欢用c++里面的STL库,所以不怎么用到数组模拟栈和队列,所以只介绍一下STL里面的栈、队列、优先队列、双端队列

stack
栈,特点是:“先进后出”
头文件:#include< stack >
 stack<Type> stk;//定义栈,Type为数据类型
 stk.size();//返回栈中的元素个数
 stk.empty();//判断栈是否为空
 stk.push(x);//向栈顶插入一个元素x 
 stk.top();//返回栈顶元素 
 stk.pop(); //弹出栈顶元素
 
queue
队列,特点是:“先进先出”
 queue<T> q;//定义队列,Type为数据类型
 q.push(x);//把x放进队列
 q.front();//返回队首元素,但不会删除
 q.pop();//删除队首元素
 q.back();//返回队尾元素,但不会删除
 q.size();//返回队列中的元素个数
 q.empty();//判断队列是否为空
 
priority_queue
优先队列,是数据结构中的堆,默认大根堆,按照从小到大排列
 priority_queue<int> q;//定义优先队列,Type为数据类型
 q.empty();//判断优先队列是否为空
 q.pop();//删除第一个元素
 q.push(x);//添加一个元素x
 q.size();//返回优先队列中的元素个数
 q.top();//返回优先队列中有最高优先级的元素
如果想变成小根堆
 1. 插入的时候直接插入-x
 2. 定义直接定义成小根堆
  priority_queue<Type,vector<Type>,greater<Type>> q;//定义小根堆,Type为数据类型
  
deque
双端队列,是一种随机访问的数据类型,提供了在序列两端快速插入和删除的功能,deque类似于vector
 deque<Type> q;////定义双端队列,Type为数据类型
 q.push_back(x);//在队尾添加元素x
 q.push_front(x);//在队头添加元素x
 q.pop_back();//删除队尾元素
 q.pop_front();//删除队头元素
 q.front();//获得队头元素
 q.back();//获得队尾元素
 q.size();//返回队列中的元素个数
 q.empty();//判断队列是否为空

3,单调栈

    int n;
    stack<int> stk;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        //如果栈不为空,并且栈顶元素大于等于x,弹出栈顶元素
        while (stk.size() && stk.top() >= x) stk.pop();
        //如果栈不为空,栈顶元素即为最近的小于x的数
        if (stk.size()) cout << stk.top() << " ";
        //否则,不存在
        else cout << -1 << " ";
        stk.push(x);
    }

4,单调队列

    int n, k;
    //单调队列,队头为答案
    deque<int> q;
    cin >> n >> k;
    
    for (int i = 0; i < n; i++) cin >> a[i];
    //输出滑动窗口中的最小值
    for (int i = 0; i < n; i++) {
        //如果队列不为空,并且窗口长度大于k,说明队头元素滑出窗口
        if (q.size() && i - q.front() + 1 > k) q.pop_front();
        //如果队列不为空,并且队尾大于等于a[i],弹出队尾
        while (q.size() && a[q.back()] >= a[i]) q.pop_back();
        q.push_back(i);
        if (i + 1 >= k) cout << a[q.front()] << " ";
    }
    
    cout << endl;
    q.clear();
    //输出滑动窗口中的最大值
    for (int i = 0; i < n; i++) {
        if (q.size() && i - q.front() + 1 > k) q.pop_front();
        while (q.size() && a[q.back()] <= a[i]) q.pop_back();
        q.push_back(i);
        if (i + 1 >= k) cout << a[q.front()] << " ";
    }

5,KMP

    int n, m;
    //字符串S,模式串P
    cin >> n >> p + 1 >> m >> s + 1;
    //求p的next数组,相当于p与p本身做匹配
    for (int i = 2, j = 0; i <= n; i++) {
        //如果j不为0,并且p[i]不等于p[j + 1],那j跳到next[j]
        while (j && p[i] != p[j + 1]) j = ne[j];
        //如果匹配,j++
        if (p[i] == p[j + 1]) j++;
        //每次记录next[i]
        ne[i] = j;
    }
    //匹配
    for (int i = 1, j = 0; i <= m; i++) {
        //如果j不为0,并且s[i]和p[j + 1]不匹配,那j就跳到next[j]
        while (j && s[i] != p[j + 1]) j = ne[j];
        //如果匹配,j++
        if (s[i] == p[j + 1]) j++;
        //如果j等于p的长度
        if (j == n) {
            //输出起始位置
            cout << i - n << " ";
            //继续匹配下一个
            j = ne[j];
        }
    }

6,并查集

    //返回x的祖先节点 + 路径压缩
    int find(int x) {
        //祖先节点的父节点是自己本身
        //将x的父亲置为x父亲的祖先节点,实现路径的压缩
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    cin >> n >> m;

    //初始化,将当前数据的父节点指向自己
    for (int i = 1; i <= n; i++) p[i] = i;

    while (m--) {
        char op;
        int a, b;
        cin >> op >> a >> b;

        if (op == 'M') {
            //将a,b所在集合合并,即将一方设为另一方的父节点
            //p[find(a)] = find(b)或者p[find(b)] = find(a);
            //把a祖先节点的父节点设为b的祖先节点
            p[find(a)] = find(b);
        }
        else {
            //如果a,b的祖先节点一样,说明在一个集合
            if (find(a) == find(b)) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容