算法總結(jié)-數(shù)據(jù)結(jié)構(gòu)

1仿耽,鏈表

鏈表可以使用結(jié)構(gòu)體+指針的方式實(shí)現(xiàn)眯搭,但是這種方式的效率很低
鏈表中最常用的是鄰接表(n個(gè)鏈表)窥翩,鄰接表的作用主要是存儲(chǔ)樹和圖
所以這里分別介紹了使用數(shù)組來(lái)實(shí)現(xiàn)單鏈表和雙鏈表的方法

單鏈表

const int N = 1e5 + 10;

//head表示頭節(jié)點(diǎn)的下標(biāo)
//e[i]表示節(jié)點(diǎn)i的值
//ne[i]表示節(jié)點(diǎn)i的next指針是多少
//idx表示當(dāng)前已經(jīng)用到了哪個(gè)點(diǎn)
int e[N], ne[N], head, idx;

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

//將x插到頭節(jié)點(diǎn)后面
void add_to_head(int x) {
    e[idx] = x;
    ne[idx] = head;
    head = idx;
    idx++;
}

//將x插到下標(biāo)為k的節(jié)點(diǎn)后面
void add(int k, int x) {
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx;
    idx++;
}

//將下標(biāo)為k的節(jié)點(diǎn)后面的節(jié)點(diǎn)刪除
void remove(int k) {
    ne[k] = ne[ne[k]];
}

雙鏈表

const int N = 1e5 + 10;

//e[i]表示下標(biāo)為i的值
//l[i]表示下標(biāo)為i的左指針
//r[i]表示下標(biāo)為i的右指針
//idx表示當(dāng)前可用的下標(biāo)
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;
}

//在下標(biāo)為a的節(jié)點(diǎn)右邊插入x
void insert(int a, int x) {
    //先設(shè)置idx的值,左右指針
    e[idx] = x;
    r[idx] = r[a];
    l[idx] = l[r[a]];
    //然后將a后面的節(jié)點(diǎn)的左指針指向idx
    l[r[a]] = idx;
    //將a的右指針指向idx
    r[a] = idx;
    idx++;
}

//刪除下標(biāo)為a的節(jié)點(diǎn)
void remove(int a) {
    l[r[a]] = l[a];
    r[l[a]] = r[a];
}

2繁扎,棧和隊(duì)列

因?yàn)閭€(gè)人比較喜歡用c++里面的STL庫(kù)幔荒,所以不怎么用到數(shù)組模擬棧和隊(duì)列,所以只介紹一下STL里面的棧梳玫、隊(duì)列爹梁、優(yōu)先隊(duì)列、雙端隊(duì)列

stack
棧提澎,特點(diǎn)是:“先進(jìn)后出”
頭文件:#include< stack >
 stack<Type> stk;//定義棧姚垃,Type為數(shù)據(jù)類型
 stk.size();//返回棧中的元素個(gè)數(shù)
 stk.empty();//判斷棧是否為空
 stk.push(x);//向棧頂插入一個(gè)元素x 
 stk.top();//返回棧頂元素 
 stk.pop(); //彈出棧頂元素
 
queue
隊(duì)列,特點(diǎn)是:“先進(jìn)先出”
 queue<T> q;//定義隊(duì)列盼忌,Type為數(shù)據(jù)類型
 q.push(x);//把x放進(jìn)隊(duì)列
 q.front();//返回隊(duì)首元素积糯,但不會(huì)刪除
 q.pop();//刪除隊(duì)首元素
 q.back();//返回隊(duì)尾元素掂墓,但不會(huì)刪除
 q.size();//返回隊(duì)列中的元素個(gè)數(shù)
 q.empty();//判斷隊(duì)列是否為空
 
priority_queue
優(yōu)先隊(duì)列,是數(shù)據(jù)結(jié)構(gòu)中的堆看成,默認(rèn)大根堆君编,按照從小到大排列
 priority_queue<int> q;//定義優(yōu)先隊(duì)列,Type為數(shù)據(jù)類型
 q.empty();//判斷優(yōu)先隊(duì)列是否為空
 q.pop();//刪除第一個(gè)元素
 q.push(x);//添加一個(gè)元素x
 q.size();//返回優(yōu)先隊(duì)列中的元素個(gè)數(shù)
 q.top();//返回優(yōu)先隊(duì)列中有最高優(yōu)先級(jí)的元素
如果想變成小根堆
 1. 插入的時(shí)候直接插入-x
 2. 定義直接定義成小根堆
  priority_queue<Type,vector<Type>,greater<Type>> q;//定義小根堆川慌,Type為數(shù)據(jù)類型
  
deque
雙端隊(duì)列吃嘿,是一種隨機(jī)訪問(wèn)的數(shù)據(jù)類型,提供了在序列兩端快速插入和刪除的功能梦重,deque類似于vector
 deque<Type> q;////定義雙端隊(duì)列兑燥,Type為數(shù)據(jù)類型
 q.push_back(x);//在隊(duì)尾添加元素x
 q.push_front(x);//在隊(duì)頭添加元素x
 q.pop_back();//刪除隊(duì)尾元素
 q.pop_front();//刪除隊(duì)頭元素
 q.front();//獲得隊(duì)頭元素
 q.back();//獲得隊(duì)尾元素
 q.size();//返回隊(duì)列中的元素個(gè)數(shù)
 q.empty();//判斷隊(duì)列是否為空

3,單調(diào)棧

    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的數(shù)
        if (stk.size()) cout << stk.top() << " ";
        //否則蚓胸,不存在
        else cout << -1 << " ";
        stk.push(x);
    }

4挣饥,單調(diào)隊(duì)列

    int n, k;
    //單調(diào)隊(duì)列,隊(duì)頭為答案
    deque<int> q;
    cin >> n >> k;
    
    for (int i = 0; i < n; i++) cin >> a[i];
    //輸出滑動(dòng)窗口中的最小值
    for (int i = 0; i < n; i++) {
        //如果隊(duì)列不為空赢织,并且窗口長(zhǎng)度大于k亮靴,說(shuō)明隊(duì)頭元素滑出窗口
        if (q.size() && i - q.front() + 1 > k) q.pop_front();
        //如果隊(duì)列不為空,并且隊(duì)尾大于等于a[i]于置,彈出隊(duì)尾
        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();
    //輸出滑動(dòng)窗口中的最大值
    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數(shù)組八毯,相當(dāng)于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的長(zhǎng)度
        if (j == n) {
            //輸出起始位置
            cout << i - n << " ";
            //繼續(xù)匹配下一個(gè)
            j = ne[j];
        }
    }

6乳讥,并查集

    //返回x的祖先節(jié)點(diǎn) + 路徑壓縮
    int find(int x) {
        //祖先節(jié)點(diǎn)的父節(jié)點(diǎn)是自己本身
        //將x的父親置為x父親的祖先節(jié)點(diǎn),實(shí)現(xiàn)路徑的壓縮
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    cin >> n >> m;

    //初始化,將當(dāng)前數(shù)據(jù)的父節(jié)點(diǎn)指向自己
    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所在集合合并云石,即將一方設(shè)為另一方的父節(jié)點(diǎn)
            //p[find(a)] = find(b)或者p[find(b)] = find(a);
            //把a(bǔ)祖先節(jié)點(diǎn)的父節(jié)點(diǎn)設(shè)為b的祖先節(jié)點(diǎn)
            p[find(a)] = find(b);
        }
        else {
            //如果a,b的祖先節(jié)點(diǎn)一樣研乒,說(shuō)明在一個(gè)集合
            if (find(a) == find(b)) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末汹忠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宽菜,老刑警劉巖谣膳,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異铅乡,居然都是意外死亡继谚,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門隆判,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)犬庇,“玉大人,你說(shuō)我怎么就攤上這事侨嘀。” “怎么了捂襟?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵咬腕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我葬荷,道長(zhǎng)涨共,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任宠漩,我火速辦了婚禮举反,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扒吁。我一直安慰自己火鼻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布雕崩。 她就那樣靜靜地躺著魁索,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盼铁。 梳的紋絲不亂的頭發(fā)上粗蔚,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音饶火,去河邊找鬼鹏控。 笑死,一個(gè)胖子當(dāng)著我的面吹牛肤寝,可吹牛的內(nèi)容都是我干的当辐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼醒陆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瀑构!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寺晌,失蹤者是張志新(化名)和其女友劉穎世吨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呻征,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耘婚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陆赋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沐祷。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖攒岛,靈堂內(nèi)的尸體忽然破棺而出赖临,到底是詐尸還是另有隱情,我是刑警寧澤灾锯,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布兢榨,位于F島的核電站,受9級(jí)特大地震影響顺饮,放射性物質(zhì)發(fā)生泄漏吵聪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一兼雄、第九天 我趴在偏房一處隱蔽的房頂上張望吟逝。 院中可真熱鬧,春花似錦赦肋、人聲如沸块攒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)局蚀。三九已至,卻和暖如春恕稠,著一層夾襖步出監(jiān)牢的瞬間琅绅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工鹅巍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留千扶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓骆捧,卻偏偏與公主長(zhǎng)得像澎羞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子敛苇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容