Standard Template Library
10th Sep 2019 by Sean Liu
這些要會自己實作!雖然有模板可以用,但是還是強烈建議要自己會寫一個。
以上的Heap如果可以自己實作出來會很好!至於平衡樹現在還不急學,會用就好了。
const int maxN = 1e5;
int stack[maxN], head = 0;
void push(int x){
if(head == maxN){
cout << "Stack is full!" << endl;
return;
} else {
stack[head] = x;
head++:
}
}
int pop(){
if(!head){ //if(head == 0)
cout << "Stack is empty!" << endl;
return -1; //代表沒有東西了!
} else {
int t = stack[head - 1];
head--;
}
}
const int maxN = 1e5;
int queue[maxN], head = 0, tail = 0; //含head, 不含tail
void enqueue(int x){ //push()
if(tail == maxN){
cout << "Queue Full!" << endl;
return;
} else {
queue[tail] = x;
tail++;
}
}
int dequeue(){ //pop()
if(head == tail){
cout << "Queue Empty!" << endl;
return -1;
} else {
int t = queue[head];
head++;
return t;
}
}
只能push maxN次!
const int maxN = 1e5;
bool isFull = false;
int queue[maxN], head = 0, tail = 0; //含head, 不含tail
void enqueue(int x){ //push()
if(tail == head){
cout << "Queue Full!" << endl;
return;
} else {
queue[tail] = x;
tail = (tail + 1) % maxN;
if(tail == head){
isFull = true;
}
}
}
int dequeue(){ //pop()
if(head == tail && !isFull){
cout << "Queue Empty!" << endl;
return -1;
} else {
int t = queue[head];
head++;
return t;
}
}
也不給code了,好煩哦 = =
也就是,雖然是可以什麼都用deque,但是如果你用stack或queue,別人(包括以後的你)比較能看出你用這個資料結構想要做什麼,不論是競賽中debug或日後寫project需要維護都很有用!
如果不止知道要知道下一個是誰,
還要知道前一個是誰的話,就得變成雙向!
struct node {
node *prev, *next;
int id;
node(): prev(NULL), next(NULL){}
};
vector<node*> List;
// list[x] 儲存指向 id = x 的指標
void Init(){ //初始化
List[0] = new node; // 起始空節點
List[0]->id = 0;
}
int prev(int x){ // 查詢前一項的 id
if(List[x] && List[x]->prev)
return List[x]->prev->id;
return -1;
}
int next(int x){ // 查詢下一項的 id
if(List[x] && List[x]->next)
return List[x]->next->id;
return -1;
}
bool Insert(int x, int id) {
// 在 id = x 的節點之後插入 id = id 的節點
if(!List[x]) return false;
node *n = new node;
List[id] = n;
n->next = List[x]->next;
if(n->next) n->next->prev = n;
List[x]->next = n;
n->prev = List[x];
n->id = id;
return true;
}
bool Delete(int x){
// 刪除 id = x 的節點
if(!List[x]) return false;
if(List[x]->next)
List[x]->next->prev = List[x]->prev;
List[x]->prev->next = List[x]->next;
delete List[x];
List[x] = NULL;
return true;
}
void travel(){ // 依序尋訪所有節點
node *s = List[0]->next; // start
while(s){
printf("%d ",s->id);
s = s->next;
}
puts("");
}
基本的功能
bool Insert(int x, int id) {
// 在 id = x 的節點之後插入 id = id 的節點
if(!List[x]) return false;
node *n = new node;
List[id] = n;
n->next = List[x]->next;
if(n->next) n->next->prev = n;
List[x]->next = n;
n->prev = List[x];
n->id = id;
return true;
}
bool Delete(int x){
// 刪除 id = x 的節點
if(!List[x]) return false;
if(List[x]->next)
List[x]->next->prev = List[x]->prev;
List[x]->prev->next = List[x]->next;
delete List[x];
List[x] = NULL;
return true;
}
void travel(){ // 依序尋訪所有節點
node *s = List[0]->next; // start
while(s){
printf("%d ",s->id);
s = s->next;
}
puts("");
}
進階功能 —— 插入和刪除
寫的時候自己畫圖!很重要!
符合 Max Heap Property
也就是對於一個節點,他的值會不比其子樹的所有數字小(反過來的話,稱為Min Heap Property)
每一個數字都存成一個樹上的節點!
根節點(最上面的)是最大/小值!
他是一個平衡二元樹,即他可能除了最後一層之外,每一層都是填滿的!而且,最後一層會從左邊填到右邊。這個性質讓我們可以用一個array來存他,一個位於 i 的節點的左、右子節點位於 2i, 2i + 1。(1base的話;否則是2i + 1, 2i + 2)
先把節點插入最後的位置,然後只要目前的節點比他的前一個節點還大,就交換兩者
先刪除根節點,然後將目前最後的節點換上去,再開始:其子節點大,若比目前大就換上來,然後遞迴下去;否則停止。
這是講師第一次實作Heap qwq
const int maxN = 1e5;
int heap[maxN], sz = 1; //一開始所有的數字都是無限大
int getMax(){
return heap[1];
}
void Insert(int x){
heap[sz] = x;
int ind = sz;
sz++;
while(heap[ind] > heap[ind/2]){
swap(heap[ind], heap[ind/2]);
ind /= 2;
}
}
void Delete(){
swap(heap[sz], heap[0]);
sz--;
int ind = 1;
while(max(heap[2*ind, 2 * ind + 1]) > heap[ind]){
if(heap[2 * ind] > heap[2 * ind + 1]){
swap(heap[ind], heap[2 * ind]);
ind = 2 * ind;
} else {
swap(heap[ind], heap[2 * ind + 1]);
ind = 2 * ind + 1;
}
}
}
void Delete(){
swap(heap[sz], heap[0]);
sz--;
int ind = 1;
while(max(heap[2*ind, 2 * ind + 1]) > heap[ind]){
if(heap[2 * ind] > heap[2 * ind + 1]){
swap(heap[ind], heap[2 * ind]);
ind = 2 * ind;
} else {
swap(heap[ind], heap[2 * ind + 1]);
ind = 2 * ind + 1;
}
}
}
https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree
/* AVL Tree Implementation in C++ */
/* Harish R */
#include<iostream>
using namespace std;
class BST
{
struct node
{
int data;
node* left;
node* right;
int height;
};
node* root;
void makeEmpty(node* t)
{
if(t == NULL)
return;
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
node* insert(int x, node* t)
{
if(t == NULL)
{
t = new node;
t->data = x;
t->height = 0;
t->left = t->right = NULL;
}
else if(x < t->data)
{
t->left = insert(x, t->left);
if(height(t->left) - height(t->right) == 2)
{
if(x < t->left->data)
t = singleRightRotate(t);
else
t = doubleRightRotate(t);
}
}
else if(x > t->data)
{
t->right = insert(x, t->right);
if(height(t->right) - height(t->left) == 2)
{
if(x > t->right->data)
t = singleLeftRotate(t);
else
t = doubleLeftRotate(t);
}
}
t->height = max(height(t->left), height(t->right))+1;
return t;
}
node* singleRightRotate(node* &t)
{
node* u = t->left;
t->left = u->right;
u->right = t;
t->height = max(height(t->left), height(t->right))+1;
u->height = max(height(u->left), t->height)+1;
return u;
}
node* singleLeftRotate(node* &t)
{
node* u = t->right;
t->right = u->left;
u->left = t;
t->height = max(height(t->left), height(t->right))+1;
u->height = max(height(t->right), t->height)+1 ;
return u;
}
node* doubleLeftRotate(node* &t)
{
t->right = singleRightRotate(t->right);
return singleLeftRotate(t);
}
node* doubleRightRotate(node* &t)
{
t->left = singleLeftRotate(t->left);
return singleRightRotate(t);
}
node* findMin(node* t)
{
if(t == NULL)
return NULL;
else if(t->left == NULL)
return t;
else
return findMin(t->left);
}
node* findMax(node* t)
{
if(t == NULL)
return NULL;
else if(t->right == NULL)
return t;
else
return findMax(t->right);
}
node* remove(int x, node* t)
{
node* temp;
// Element not found
if(t == NULL)
return NULL;
// Searching for element
else if(x < t->data)
t->left = remove(x, t->left);
else if(x > t->data)
t->right = remove(x, t->right);
// Element found
// With 2 children
else if(t->left && t->right)
{
temp = findMin(t->right);
t->data = temp->data;
t->right = remove(t->data, t->right);
}
// With one or zero child
else
{
temp = t;
if(t->left == NULL)
t = t->right;
else if(t->right == NULL)
t = t->left;
delete temp;
}
if(t == NULL)
return t;
t->height = max(height(t->left), height(t->right))+1;
// If node is unbalanced
// If left node is deleted, right case
if(height(t->left) - height(t->right) == 2)
{
// right right case
if(height(t->left->left) - height(t->left->right) == 1)
return singleLeftRotate(t);
// right left case
else
return doubleLeftRotate(t);
}
// If right node is deleted, left case
else if(height(t->right) - height(t->left) == 2)
{
// left left case
if(height(t->right->right) - height(t->right->left) == 1)
return singleRightRotate(t);
// left right case
else
return doubleRightRotate(t);
}
return t;
}
int height(node* t)
{
return (t == NULL ? -1 : t->height);
}
int getBalance(node* t)
{
if(t == NULL)
return 0;
else
return height(t->left) - height(t->right);
}
void inorder(node* t)
{
if(t == NULL)
return;
inorder(t->left);
cout << t->data << " ";
inorder(t->right);
}
public:
BST()
{
root = NULL;
}
void insert(int x)
{
root = insert(x, root);
}
void remove(int x)
{
root = remove(x, root);
}
void display()
{
inorder(root);
cout << endl;
}
};
#include <stack> //引用stack
stack<int> stk; //這個stack裡面裝的是int
int main(){
stk.push(5); //放進去一個值為5的數字
cout << stk.top() << endl; //stk.top()代表最上面的數字, 5
stk.pop(); //拿出來
}
#include <queue> //引用queue
queue<int> que; //這個queue裡面裝的是int
int main(){
que.push(5); //放進去一個值為5的數字
que.push(7);
cout << que.front() << endl; //que.top()代表最前面的數字, 5
que.pop(); //拿出來
cout << que.front() << endl; //7
}
#include <deque> //引用deque
deque<int> dq; //這個dequeue裡面裝的是int
int main(){
dq.push_front(3); //將3放在deque最前面
dq.push_back(7); //將7放在deque最後面
dq.push_front(5);
cout << dq.front() << endl; //最前面的數字, 5
cout << dq.back() << endl; //最後面的數字, 7
dq.pop_back(); //將最前面的數字拿出來
dq.pop_front(); //將最後面的數字拿出來
cout << dq[0] << endl; //可以隨機存取!, 3
}
#include <queue> //引用queue - priority_queue在queue裡面
#include <vector>
priority_queue<int> pq; //這個priority_queue裡面裝int
int main(){
pq.push(5); //將一個數字放進去
pq.push(7);
pq.push(3);
pq.push(2);
cout << pq.top() << endl; //拿出最大值,7
pq.pop(); //刪除最大值
cout << pq.top() << endl; //拿出最大值,5
}
#include <queue> //引用queue - priority_queue在queue裡面
#include <vector>
class Cmp{
public:
bool operator()(int a, int b){ //a < b
return a < b;
}
}
priority_queue<int, vector<int>, Cmp > pq; //型別, 容器, 比較
#include <set> //引用set
set<int> st;
int main(){
st.insert(5); //放入5
cout << st.count(5) << endl; //有沒有 5?
cout << st.size() << endl; //st裡面有幾個元素
st.erase(5); //將5刪除
}
#include <map> //引用map
map<int, int> mp; //key, value
int main(){
mp.insert({2, 1}); //用大括弧包起來就行了
cout << mp[2] << endl; //2所對應到的值:1
cout << mp.count(3) << endl; //有沒有索引值為3的? 0
}
可能有點超時了?有問題記得問,可以去密學長!