前言:
緊張的學習又開始了.
想想上週學了什麼.
正文
堆(優先隊列)
又是一種奇怪的東西但是省時省力,簡單粗暴.
堆數據結構是一種數組對象,它可以被視爲一棵完全二叉樹結構。
堆結構的二叉樹存儲是:
最大堆:每個父節點的都大於孩子節點。
最小堆:每個父節點的都小於孩子節點。
兩個最重要的是PUSH和POP。 PUSH操作在堆棧的頂部加入一 個元素。POP操作相反, 在堆棧頂部移去一個元素, 並將堆棧的大小減一。於是優先隊列就由此生髮出來了.
由於,堆的高度是log_n的,所以不論插入還是輸出都是log_n的複雜度.
#include <bits/stdc++.h>
using namespace std;
const int N = 300000;
struct Heap {
int heap[N + 10];
int size;
void init() {
size = 1;
}
void push (int x) {
int i = size++;
while (i > 1) {
int p = (i >> 1);
if (heap[p] > x) {
break;
}
heap[i] = heap[p];
i = p;
}
heap[i] = x;
}
int pop() {
int ret = heap[1];
int x = heap[--size];
int i = 1;
while ((i << 1) < size) {
int lson = (i << 1);
int rson = (i << 1 | 1);
if (rson < size && heap[rson] > heap[lson]) lson = rson;
if (heap[lson] < x) {
break;
}
heap[i] = heap[lson];
i = lson;
}
heap[i] = x;
return ret;
}
bool empty() {
return size == 0;
}
};
int a[N];
int main () {
srand(time(NULL));
Heap my_heap;
my_heap.init();
for (int i = 0; i < N; i++) {
a[i] = rand()*rand();
}
//start here
clock_t mystart = clock();
for (int i = 0; i < N; i++) {
my_heap.push(a[i]);
}
while(!my_heap.empty()) {
my_heap.pop();
}
clock_t myend = clock();
//end here
priority_queue<int> heap;
clock_t start = clock();
for (int i = 0; i < N; i++) {
heap.push(a[i]);
}
while(!heap.empty()) {
// cout << heap.top() << endl;
heap.pop();
}
clock_t end = clock();
cout << "Running time of xjoi machine is:" << static_cast<double> (myend-mystart)/CLOCKS_PER_SEC*1000 << "ms" << endl;
cout << "Running time stl is:" << static_cast<double> (end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
return 0;
}
以上程序不是我打的……
此程序是大頭堆的模板,可以測試手寫堆的速度.當然可以用c++自帶的堆明顯手寫的更快.
利用優先隊列可以自動調整自身的元素,可以完成很多易超時的題目.
鄰接表
奇怪的東西*2.
對於圖來說,鄰接矩陣是不錯的一種圖存儲結構,但是我們也發現,對於邊數相對頂點較少的圖,這種結構是存在對存儲空間的極大浪費的。因此我們考慮另外一種存儲結構方式:鄰接表(Adjacency List),即數組與鏈表相結合的存儲方法。
鄰接表是圖的一種最主要存儲結構,用來描述圖上的每一個點。對圖的每個頂點建立一個容器(n個頂點建立n個容器),第i個容器中的結點包含頂點Vi的所有鄰接頂點。實際上我們常用的鄰接矩陣就是一種未離散化每個點的邊集的鄰接表。
在有向圖中,描述每個點向別的節點連的邊(點a->點b這種情況)。
在無向圖中,描述每個點所有的邊(點a-點b這種情況)
#include<bits/stdc++.h>
using namespace std;
#define N 1000000
int first[N],next[N],point[N];
int E;
void f(int a,int b)
{
point[E]=b;
next[E]=first[a];
first[a]=E;
E++;
}
int main()
{
memset(first,-1,sizeof(first));
int a,c,d;
cin>>a;
E=0;
for(int i=1; i<=a; i++)
{
cin>>c>>d;
f(c,d);
f(d,c);
}
for(int i=1; i<=a; i++)
{
cout<<i<<":";
for(int j=first[i]; j!=-1; j=next[j])
cout<<point[j];
cout<<endl;
}
return 0;
}
以上就是一個鄰接表的模板.
在寫題的時候可以利用鄰接表來儲存較大的數據和關係圖.
在很多時候鄰接表十分有用,在之前寫的博客裏就有提及鄰接表的.
一週要點:
- 看題看不懂浪費大量時間.
- if和while語句中少了一個等號.
- 知識掌握後不會使用.