1. 程式人生 > 其它 >VBA 4:worksheets 工作表物件 add、delete、copy、count、name、批量新增表、批量刪除表、彙總

VBA 4:worksheets 工作表物件 add、delete、copy、count、name、批量新增表、批量刪除表、彙總

目錄

一、定義

二、構造

1、具象形狀

2、建佇列

3、入隊

4、出隊

5、檢視隊首元素

6、判斷佇列是否為空

7、佇列的大小

三、結尾

定義

  • 一種資料結構

  • 一種特殊的線性表

  • 遵循先進先出\((First\;In\;Last\;Out)\)原則

構造

 具象形狀

  日常生活中,有序的排隊是常有的事,比如說學生黨排隊打飯之類的。

  並且顯而易見的,先排隊的人先打到飯。(應該不會有人插隊吧)

  所以我們這群優雅人士,給排隊乾飯之類的一系列事情統一了一個結構,佇列

返回目錄

 建佇列

  我們既然要給資料排隊,那麼我們就必須要給資料一個排隊的視窗,對吧?

  所以我們使用佇列的第一步,就是給佇列一個頭。

  • STL版

  我們需要先引入queue這個為我們封裝好佇列的基本函式的庫,然後建立佇列。

#include <queue>
using namespace std;
queue</*資料型別*/> /*變數名*/;
// 比如:
#include <queue>
using namespace std;
queue<int> Q;

  但是,由於我不喜歡用

using namespace std;

  所以,我一般這麼寫。

#include <queue>
std::queue<int> Q;
  • 手打版

  首先,要明確的一點就是我們手打佇列需要指明佇列的頭和尾,所以我們需要定義頭和尾的指標與佇列的大小。

/*資料型別*/ /*變數名*/[/*陣列大小*/];
/*資料型別*/ /*作為頭指標的變數名*/;
/*資料型別*/ /*作為尾指標的變數名*/;
// 比如:
int Q[100001]; // 佇列存放資料的大小
int head = 1;  // 佇列的頭指標
int tail = 0;  // 佇列的尾指標

  這裡我們定義了尾指標的大小為0,而頭指標的大小為1,是為什麼呢?

  我們可以想象一下,什麼時候頭指標會在尾指標後面呢?

  很顯然就是佇列裡面沒有元素,所以尾指標會閒得發慌,跑到頭指標的前面(出頭鳥),對吧?

返回目錄

 入隊

  我們以上面乾飯的學生為例。

  如果,你也要當個乾飯的學生(我說的是如果),那麼就必須要先排隊打飯才能幹對不對?

  同樣的如果我們要讓資料們有次序的被利用,那麼我們就需要先讓資料排好隊。

  而排好隊的前提就是讓資料去排隊,所以就有了我們的入隊操作。

  • STL版

  運用queue庫裡面的push()函式,就可以輕易的將資料入隊了。

  我們以上面開的int型別的數列來演示。

int a;
Q.push(a);
  • 手打版

  很明顯的,當我們需要將資料排進佇列裡面,而佇列還沒有出去一個人的時候,隊伍的尾巴會變長。

void push(int a) {
    ++tail;
    Q[tail] = a;
}

返回目錄

 出隊

  當我們打完飯就要去幹飯的對不對,那我們不可能賴在隊伍裡面吧?

  所以我們要離開隊伍。

  這個資料的離隊叫做出隊操作。

  • STL版

  queue庫裡面提供了一個出隊函式,叫做pop()

Q.pop();
  • 手打版

  我們知道,佇列的原則是\(FIFO\),所以我們每次出隊的時候出隊的都是隊首。

void pop() {
    ++head;
}

  我們將頭指標往後移動了一個,隊首變為原來的下一個,相當於原來那個出了佇列,這樣一來就不用去維護頭指標永遠是1的位置,就相當於用少量的空間來取代大量的時間。

  因為如果我們維護頭指標永遠為1的話,每次出隊都將用\(O(n)\)的時間來將整個用陣列維護的佇列前移,會導致程式執行時間超過題目的限制。

返回目錄

 檢視隊首元素

  有的學校排隊打飯時用的是餐卡(至少我們學校是),用餐卡就會記錄你的消費資訊。

  同樣的,有時候我們也需要記錄排過隊的資料的資訊,所以我們每次在資料出隊的時候要檢視資料幹了什麼,這個操作可以通過我們先檢視隊首元素並記錄,然後再將隊首元素出隊

  因此我們就需要檢視隊首元素這一操作。

  • STL版

  同樣,queue庫給我們提供了檢視隊首元素的函式,front()

    int a;
    a = Q.front();
  • 手打版

  還記得我們前面定義的\(head\)指標嗎?

  這時候我們要用到它了。

  因為我們定義了\(head\)指標來作為佇列的頭指標,所以?所以我們可以用\(head\)來返回隊首的元素。

int front() {
    return Q[head];
}
int main (void) {
    ...balabala...
    
    int a = front();
    
    ...balabala...
}

  這樣子就可以取到隊首的元素了。

返回目錄

 判斷佇列是否為空

  雖然我們日常生活中的排隊很容易就可以看出來還有沒有人在排隊,但是我們在程式中不能確定這個時刻我們這個佇列中還有沒有資料,所以我們需要判斷佇列是否為空

  • STL版

  要判斷佇列是否為空,queue庫給我們提供了一個函式,empty()

Q.empty();
  • 手打版

  對於我們手打的佇列,要判斷佇列是否為空,也是很簡單的。

  首先,我們可以回想一下,我們一開始定義的\(head\)指標和\(tail\)指標。

  我們一開始將\(head\)指標賦值為\(1\),而\(tail\)指標賦值為\(0\)

  這意味著什麼,意味著隊首在隊尾的後面。

  意味著這時候佇列裡面沒有任何的元素。

  所以我們判斷佇列是否為空,就等於在判斷隊首有沒有在隊尾的後面

bool empty() {
    return head > tail; // 當佇列為空,即head > tail的時候,empty()作為 檢查佇列是空的 的函式,返回true;相反的,當佇列不為空,即head ≤ tail的時候,返回false。
}

返回目錄

 佇列的大小

  我們也需要檢視佇列有多少元素,所以我們有時候需要有檢視佇列大小這個操作。

  • STL版

  檢視佇列大小,在queue庫裡叫size()

Q.size();
  • 手打版

  好傢伙,我們又要用到\(head\)\(tail\)了。

  我們一開始\(head = 1, tail = 0\)的賦值方法告訴了我們當佇列裡面有至少一個元素的時候,\(head ≤ tail\)

  也就是說,當我們佇列裡面有元素的時候,會滿足\(tail - head ≥ 0\)

  並且,當元素是\(1\)的時候,\(tail - head = 0\)

  所以我們將等式的兩邊同時加上\(1\),可以有\(tail - head + 1 = 1\)

  同樣的一開始的式子就可以變成\(tail - head + 1 ≥ 1\)

  也就是對於我們手打的佇列,隊伍中的元素個數是\(tail - head + 1\)個。

int size() {
    return (tail - head + 1);
}

返回目錄

結尾

 用STL寫的佇列 與 用手打的佇列 各有千秋,一般來說,沒有吸氧(開\(O2\)優化)的話,用手打的佇列比用STL寫的佇列來的快;吸氧(開\(O2\)優化)的話,兩者時間差不多。

 而且單說打比賽的話,從CSP到NOIP,是不可以開O2優化(2021年開啟了吸氧時代,所以當我沒說)的,所以總體上是手打佇列快。

 所以我選擇STL!!!!!

 因為STL打的快啊!!!!!(懶人必備神器

返回目錄

部落格園:https://www.cnblogs.com/Juro/

Copyright ©2021 Juro

【轉載文章務必保留出處和署名,謝謝!】