3. 演算法複雜度分析
4. 完整**
通過第三節我們知道,陣列佇列在出隊操作中需要花費o(n)的時間複雜度,原因在於出隊時需要移動大量元素。如果我們可以迴圈利用空間,那麼問題就迎刃而解。所以,迴圈佇列應運而生。迴圈佇列結構如下:
(這裡為了直觀,將佇列繪製成環形,實際記憶體依舊是連續的記憶體塊。)
首先迴圈佇列作為佇列的一種,基本特性和陣列佇列相同:
1.佇列有隊頭和隊尾兩端。
2.入隊操作只能從隊尾進行,出隊操作只能從隊頭進行。
3.先入隊的先出隊,即先進先出(first in first out),fifo。
還有乙個隱含特性,佇列可以自行擴容(縮容),而不需要使用者關心。
由上圖結構可知,隊空和隊滿時,隊頭和隊尾都指向同一塊記憶體。因為迴圈佇列和動態陣列有一定差異,所以對迴圈佇列從底層重新進行了實現。首先,依舊使用乙個由純虛函式構成的抽象類作為乙個介面來定義這些操作。具體**如下:
template
class queue
;
下面從底層重新構建乙個迴圈佇列類。
template
class loopqueue : public queue..
.private:
t *m_data;
int m_capacity;
int m_size;
int m_front;
int m_rear;
};
這個類內部定義乙個陣列,為了相容更多型別,這裡使用了泛型的概念。然後定義了佇列的容量、大小以及隊頭和隊尾。同理,構造陣列時,可以初始化佇列的佇列容量,(預設是10)隊頭和隊尾都是0。
與動態陣列類似,為了實現自行擴容(縮容),類內部建立了乙個resize函式來實現。
template
class loopqueue : public queue
else
} delete[
] m_data;
m_data = p;
m_capacity = len;
m_front =0;
m_rear = m_size;}.
..};
原理上與動態陣列類似,這裡的取餘操作保證了迴圈。下面對各種基本操作進行了重寫實現。
template
class loopqueue : public queue
m_data[m_rear]
= num;
m_size++
; m_rear =
(m_rear +1)
% m_capacity;}.
..};
入隊操作時可能會呼叫擴容函式。
template
class loopqueue : public queue
if(m_size <= m_capacity /4)
m_size--
; m_front =
(m_front +1)
% m_capacity;}.
..};
出隊操作時可能會呼叫縮容函式。
template
class loopqueue : public queue
return m_data[m_front];}
...}
;
同樣的,佇列只能獲得隊首元素,所以這裡的查詢操作也非常簡單。
template
class loopqueue : public queue..
. bool isempty()
void
print()
else}}
cout <<
"]rear"
<< endl;}.
..};
為了保證正確輸出,print函式中也採用了取餘操作。
函式最壞複雜度
平均複雜度
enqueue
o(1+n) = o(n)
o(1+1) = o(1)
最壞複雜度o(1+n)中第乙個1是指元素移動操作,第二個n是指resize函式,以下同理。
入隊可能會引發擴容操作,平均而言,每增加n個元素,會擴充套件一次,會發生n個元素的移動,所以平均下來是o(1)。
函式最壞複雜度
平均複雜度
dequeue
o(1+n) = o(n)
o(1+1) = o(1)
函式最壞複雜度
平均複雜度
front
o(1)
o(1)
總體情況:
操作時間複雜度
增o(1)
刪o(1)
查o(1)
通過第三節我們知道,陣列佇列操作的增、查都是o(1)級別的時間複雜度,而刪是o(n)級別的時間複雜度,因為每次出隊的都是隊首元素,後面的元素需要乙個個向前移動。而對於迴圈佇列,不需要移動元素,所以增、刪、查都是o(1)級別的時間複雜度,實現了對陣列佇列的優化。
注:佇列並不提供改的操作。
抽象類介面**:
#ifndef __queue_h__
#define __queue_h__
template
class queue
;#endif
迴圈佇列**:
#ifndef __loopqueue_h__
#define __loopqueue_h__
#include
"queue.h"
using namespace std;
template
class loopqueue : public queue
intsize()
void
resize
(int len)
else
} delete[
] m_data;
m_data = p;
m_capacity = len;
m_front =0;
m_rear = m_size;
} bool isempty()
void
print()
else}}
cout <<
"]rear"
<< endl;
}//入隊操作
void
enqueue
(t num)
m_data[m_rear]
= num;
m_size++
; m_rear =
(m_rear +1)
% m_capacity;
}//出隊操作
void
dequeue()
if(m_size <= m_capacity /4)
m_size--
; m_front =
(m_front +1)
% m_capacity;
}//獲得隊首元素
t front()
return m_data[m_front];}
private:
t *m_data;
int m_capacity;
int m_size;
int m_front;
int m_rear;};
#endif
資料結構的C實現 迴圈佇列
迴圈佇列 include include define ok 1 define error 0 define overflow 2 define maxsize 10 迴圈佇列的最大元素數量 typedef char elemtype 元素型別 typedef struct queue queue ...
資料結構(七) 迴圈佇列的實現 java版
介面定義 package com.cn.hbut.dao public inte ce queue 具體的實現 package com.cn.hbut.daoimpl import com.cn.hbut.dao.queue author administrator 迴圈佇列的實現 public c...
資料結構 佇列 迴圈佇列 陣列實現
佇列是一種特殊的 線性表,特殊之處在於它只允許在表的前端 front 進行刪除操作,而在表的後端 tail 進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。以陣列實現的佇列結構,如果是普通佇列,頻繁增刪元素,會造成陣列記憶體空間的大量流失,所...