模板庫(五) - 資料結構模板
阿新 • • 發佈:2019-01-07
寫在前面
“模板庫”這一系列文章用來複習
模板
由於時間原因,作者無法一一親自除錯其中的程式,也因如此,有一部分程式來自於網際網路,如果您覺得這侵犯了您的合法權益,請聯絡
刪除。
對於給您造成的不便和困擾,我表示深深的歉意。
本系列文章僅用於學習,禁止任何人或組織用於商業用途。
本系列文章中,標記*的為選學演算法,在
中較少涉及。
資料結構
佇列
【簡介】
佇列是一種特殊的線性表,特殊之處在於它只允許在表的前端 進行刪除操作,而在表的後端 進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。
#include<cstdio>
#include<queue>
using namespace std;
queue<int> q;
int n,opt,k;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&opt);
if(opt==1) scanf("%d",&k),q.push(k);
else if(opt==2) q.pop();
else printf("%d\n",q.front());
}
return 0;
}
複雜度(入隊,出隊,訪問隊首)
棧
【簡介】
棧 又名堆疊,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對地,把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。
【程式碼實現】
#include<cstdio>
#include<stack>
using namespace std;
int n,opt,k;
stack<int> s;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&opt);
if(opt==1) scanf("%d",&k),s.push(k);
else if(opt==2) s.pop();
else printf("%d\n",s.top());
}
return 0;
}
複雜度(入棧,出棧,訪問棧頂)
堆
【簡介】
堆( )是電腦科學中一類特殊的資料結構的統稱。堆通常是一個可以被看做一棵樹的陣列物件。
【程式碼實現】
二叉堆
#include<cstdio>
#include<queue>
#include<cctype>
using namespace std;
priority_queue<int,vector<int>,greater<int> > q;
inline int read(){
int x=0,f=0;char ch=getchar();
while(!isdigit(ch))f|=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+(ch^48),ch=getchar();
return f?-x:x;
}
int main(){
int m=read();
for(int i=1;i<=m;i++){
int a=read();
if(a==1){
int b=read();
q.push(b);
}
else if(a==2) printf("%d\n"q.top());
else q.pop();
}
return 0;
}
*斐波那契堆
#ifndef _FIBONACCI_TREE_HPP_
#define _FIBONACCI_TREE_HPP_
#include <iomanip>
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
template <class T>
class FibNode {
public:
T key; // 關鍵字(鍵值)
int degree; // 度數
FibNode<T> *left; // 左兄弟
FibNode<T> *right; // 右兄弟
FibNode<T> *child; // 第一個孩子節點
FibNode<T> *parent; // 父節點
bool marked; // 是否被刪除第一個孩子
FibNode(T value):key(value), degree(0), marked(false),
left(NULL),right(NULL),child(NULL),parent(NULL) {
key = value;
degree = 0;
marked = false;
left = this;
right = this;
parent = NULL;
child = NULL;
}
};
template <class T>
class FibHeap {
private:
int keyNum; // 堆中節點的總數
int maxDegree; // 最大度
FibNode<T> *min; // 最小節點(某個最小堆的根節點)
FibNode<T> **cons; // 最大度的記憶體區域
public:
FibHeap();
~FibHeap();
// 新建key對應的節點,並將其插入到斐波那契堆中
void insert(T key);
// 移除斐波那契堆中的最小節點
void removeMin();
// 將other合併到當前堆中
void combine(FibHeap<T> *other);
// 獲取斐波那契堆中最小鍵值,並儲存到pkey中;成功返回true,否則返回false。
bool minimum(T *pkey);
// 將斐波那契堆中鍵值oldkey更新為newkey
void update(T oldkey, T newkey);
// 刪除鍵值為key的節點
void remove(T key);
// 斐波那契堆中是否包含鍵值key
bool contains(T key);
// 列印斐波那契堆
void print();
// 銷燬
void destroy();
private:
// 將node從雙鏈表移除
void removeNode(FibNode<T> *node);
// 將node堆結點加入root結點之前(迴圈連結串列中)
void addNode(FibNode<T> *node, FibNode<T> *root);
// 將雙向連結串列b連結到雙向連結串列a的後面
void catList(FibNode<T> *a, FibNode<T> *b);
// 將節點node插入到斐波那契堆中
void insert(FibNode<T> *node);
// 將"堆的最小結點"從根連結串列中移除,
FibNode<T>* extractMin();
// 將node連結到root根結點
void link(FibNode<T>* node, FibNode<T>* root);
// 建立consolidate所需空間
void makeCons();
// 合併斐波那契堆的根連結串列中左右相同度數的樹
void consolidate();
// 修改度數
void renewDegree(FibNode<T> *parent, int degree);
// 將node從父節點parent的子連結中剝離出來,並使node成為"堆的根連結串列"中的一員。
void cut(FibNode<T> *node, FibNode<T> *parent);
// 對節點node進行"級聯剪下"
void cascadingCut(FibNode<T> *node) ;
// 將斐波那契堆中節點node的值減少為key
void decrease(FibNode<T> *node, T key);
// 將斐波那契堆中節點node的值增加為key
void increase(FibNode<T> *node, T key);
// 更新斐波那契堆的節點node的鍵值為key
void update(FibNode<T> *node, T key);
// 在最小堆root中查詢鍵值為key的節點
FibNode<T>* search(FibNode<T> *root, T key);
// 在斐波那契堆中查詢鍵值為key的節點
FibNode<T>* search(T key);
// 刪除結點node
void remove(FibNode<T> *node);
// 銷燬斐波那契堆
void destroyNode(FibNode<T> *node);
// 列印"斐波那契堆"
void print(FibNode<T> *node, FibNode<T> *prev, int direction);
};
/*
* 建構函式
*/
template <class T>
FibHeap<T>::FibHeap()
{
keyNum = 0;
maxDegree = 0;
min = NULL;
cons = NULL;
}
/*
* 解構函式
*/
template <class T>
FibHeap<T>::~FibHeap()
{
}
/*
* 將node從雙鏈表移除
*/
template <class T>
void FibHeap<T>::removeNode(FibNode<T> *node)
{
node->left->right = node->right;
node->right->left = node->left;
}
/*
* 將node堆結點加入root結點之前(迴圈連結串列中)
* a …… root
* a …… node …… root
*/
template <class T>
void FibHeap<T>::addNode(FibNode<T> *node, FibNode<T> *root)
{
node->left = root->left;
root->left->right = node;
node->right = root;
root->left = node;
}
/*
* 將節點node插入到斐波那契堆中
*/
template <class T>
void FibHeap<T>::insert(FibNode<T> *node)
{
if (keyNum == 0)
min = node;
else
{
addNode(node, min);
if (node->key < min->key)
min = node;
}
keyNum++;
}
/*
* 新建鍵值為key的節點,並將其插入到斐波那契堆中
*/
template <class T>
void FibHeap<T>::insert(T key)
{
FibNode<T> *node;
node = new FibNode<T>(key);
if (node == NULL)
return ;
insert(node);
}
/*
* 將雙向連結串列b連結到雙向連結串列a的後面
*
* 注意: 此處a和b都是雙向連結串列
*/
template <class T>
void FibHeap<T>::catList(FibNode<T> *a, FibNode<T> *b)
{
FibNode<T> *tmp;
tmp = a->right;
a->right = b->right;
b->right->left = a;
b->right = tmp;
tmp->left = b;
}
/*
* 將other合併到當前堆中
*/
template <class T>
void FibHeap<T>::combine(FibHeap<T> *other)
{
if (other==NULL)
return ;
if(other->maxDegree > this->maxDegree)
swap(*this, *other);
if((this->min) == NULL) // this無"最小節點"
{
this->min = other->min;
this->keyNum = other->keyNum;
free(other->cons);
delete other;
}
else if((other->min) == NULL) // this有"最小節點" && other無"最小節點"
{
free(other->cons);
delete other;
} // this有"最小節點" && other有"最小節點"
else
{
// 將"other中根連結串列"新增到"this"中
catList(this->min, other->min);
if (this->min->key > other->min->key)
this->min = other->min;
this->keyNum += other->keyNum;
free(other->cons);
delete other;
}
}
/*
* 將"堆的最小結點"從根連結串列中移除,
* 這意味著"將最小節點所屬的樹"從堆中移除!
*/
template <class T>
FibNode<T>* FibHeap<T>::extractMin()
{
FibNode<T> *p = min;
if (p == p->right)
min = NULL;
else
{
removeNode(p);
min = p->right;
}
p->left = p->right = p;
return p;
}
/*
* 將node連結到root根結點
*/
template <class T>
void FibHeap<T>::link(FibNode<T>* node, FibNode<T>* root)
{
// 將node從雙鏈表中移除
removeNode(node);
// 將node設為root的孩子
if (root->child == NULL)
root->child = node;
else
addNode(node, root->child);
node->parent = root;
root->degree++;
node->marked = false;
}
/*
* 建立consolidate所需空間
*/
template <