C++數據結構——隊列
1.簡介
像棧一樣,隊列也是一種線性表。它允許在表的一端插入數據,在另一端刪除元素。插入元素的這一端稱之為隊尾。刪除元素的這一端我們稱之為隊頭,它的特點是先進先出。
首先我們來思考一下隊列這種數據結構使用什么表的創建方式比較好,是頭插法?尾插法?之前我們有提到,隊列在隊頭刪除元素,在隊尾插入元素,如果是頭插法,那么在頭結點這邊進行插入,在另一邊進行刪除,尾插法恰恰相反。其實這兩種方法沒有本質上的區別,因為無論使用哪種方法,我們都需要有兩個標志能夠定位到插入點和刪除點,但是,我們在進行尾插法時我們就自帶了一個標志,因為每次往后增加結點時,我們需要找到當前的最后一個結點,這時的末尾結點就充當了一個標志“rear”,在頭結點處刪除,在rear處插入,我們就完成了隊列的基本操作。
2.基本結構
rear標志會隨着結點的插入而移動,始終指向末尾結點
而多數教科書或者文章中會是這樣的結構
它這里多了一個標志"front",它有什么作用呢,其實作者認為它的作用跟頭結點沒什么區別,都是為了找到隊頭,要說什么本質的區別的話,emmmmm,作者好像沒領悟出來,可能是因為在湊結構的時候能湊一對??
我們接下來的代碼將基於這種結構實現。
3.基本操作
隊列的基本操作有入隊(push)、出隊(pop)、判空(isEmpty)、讀取隊頭元素(getFront)、返回隊列大小(getSize)
3.1隊列的類型聲明
typedef struct queue* Queue;
typedef struct node* Node;
struct node{
int element;
Node next;
};
//隊列結構
struct queue{
Node front;
Node rear;
int size;
};
3.2入隊
void push(Queue q,int x){
Node temp=new node;
temp->element=x;
temp->next=NULL;//由於我們用的是尾插法,所以我們插入的結點的next必定是指向NULL,
//我們也可以換成temp->next=q->rear->next;
q->rear->next=temp;
q->rear=temp; //這兩步將rear移動到temp上
q->size++;
}
3.3出隊
刪除三步走(實際代碼就①②兩步),在刪除的時候我們還會遇到一個問題,在刪除了最后一個元素后我們該怎么辦
如圖,在刪除結點4后,我們只需要把rear標志放到front處就變成了我們初始化隊列時的樣子
void pop(Queue q)
{
if(isEmpty(q))
return ;
Node temp;
temp=q->front->next;
q->front->next=temp->next;//刪除隊頭
if(q->rear==temp)//如果隊尾就是我們要刪除的元素,就代表已經是最后一個元素了
q->rear=q->front;
delete(temp);//刪除的最后記得把內存釋放
q->size--;
}
3.4判空
void isEmpty(Queue q){
return q->front==q->rear;//隊頭隊尾在一起說明隊列為空
}
3.5獲取隊頭元素
int getFront(Queue q){
return q->front->next->element;
}
3.6獲取隊列長度
int getSize(Queue q){
return q->size;
}
4.完整代碼
#include<iostream>
using namespace std;
typedef struct queue* Queue;
typedef struct node* Node;
struct node{
int element;
Node next;
};
struct queue{
Node front;
Node rear;
int size;
};
void init(Queue q){
q->front=q->rear=new node;
q->front->next=NULL;
q->size=0;
}
bool isEmpty(Queue q){
return q->front==q->rear;
}
void push(Queue q,int x){
Node temp=new node;
temp->element=x;
temp->next=NULL;
q->rear->next=temp;
q->rear=temp;
q->size++;
}
void pop(Queue q)
{
if(isEmpty(q))
return ;
Node temp=new node;
temp=q->front->next;
q->front->next=temp->next;
if(q->rear==temp)
q->rear=q->front;
delete(temp);
q->size--;
}
void print(Node head){
while(head->next){
cout<<head->next->element<<" ";
head=head->next;
}
cout<<endl;
}
int getFront(Queue q){
return q->front->next->element;
}
int getSize(Queue q){
return q->size;
}
int main(){
Queue q=new queue;
init(q);
Node head=new node;
head=q->front;
for(int i=0;i<5;i++){
push(q,i+1);
}
print(head);
pop(q);
print(head);
push(q,20);
pop(q);
print(head);
cout<<getFront(q)<<endl;
cout<<getSize(q)<<endl;
return 0;
}