資料結構——迴圈佇列PTA習題

流楚丶格念發表於2020-12-17

單選題

題號題目答案
1所謂“迴圈佇列”是指用單向迴圈連結串列或者迴圈陣列表示的佇列。
2在用陣列表示的迴圈佇列中,front值一定小於等於rear值。
3為解決計算機主機與印表機之間速度不匹配問題,通常設定一個列印資料緩衝區,主機將要輸出的資料依次寫入該緩衝區,而印表機則依次從該緩衝區中取出資料。該緩衝區的邏輯結構應該是? 佇列
4若已知一佇列用單向連結串列表示,該單向連結串列的當前狀態(含3個物件)是:1->2->3,其中x->y表示x的下一節點是y。此時,如果將物件4入隊,然後佇列頭的物件出隊,則單向連結串列的狀態是: 2->3->4
5某佇列允許在其兩端進行入隊操作,但僅允許在一端進行出隊操作。若元素a、b、c、d、e依次入此佇列後再進行出隊操作,則不可能得到的出隊序列是: d b c a e
6若用大小為6的陣列來實現迴圈佇列,且當前front和rear的值分別為0和4。當從佇列中刪除兩個元素,再加入兩個元素後,front和rear的值分別為多少? 2和0
7如果迴圈佇列用大小為m的陣列表示,且用隊頭指標front和佇列元素個數size代替一般迴圈佇列中的front和rear指標來表示佇列的範圍,那麼這樣的迴圈佇列可以容納的元素個數最多為: m
8在一個不帶頭結點的非空鏈式佇列中,假設f和r分別為隊頭和隊尾指標,則插入s所指的結點運算是( )。 r->next=s; r=s;
9迴圈順序佇列中是否可以插入下一個元素() 與隊頭指標和隊尾指標的值有關
10現有佇列 Q 與棧 S,初始時 Q 中的元素依次是{ 1, 2, 3, 4, 5, 6 }(1在隊頭),S 為空。若允許下列3種操作:(1)出隊並輸出出隊元素;(2)出隊並將出隊元素入棧;(3)出棧並輸出出棧元素,則不能得到的輸出序列是: 3, 4, 5, 6, 1, 2

題解

  1. 初始化建立空佇列時,令front=rear=0,每當插入新的佇列尾元素時,rear增1,每當刪除一個佇列首元素時,front增1。因此,在非空佇列中,頭指標始終指向佇列頭元素,而尾指標始終指向佇列尾元素的下一個位置。
    front :0+2=2,
    rear 4+2=6——>0.

函式題

6-1 另類迴圈佇列 (20分)

如果用一個迴圈陣列表示佇列,並且只設佇列頭指標Front,不設尾指標Rear,而是另設Count記錄佇列中元素個數。請編寫演算法實現佇列的入隊和出隊操作。

函式介面定義:

bool AddQ( Queue Q, ElementType X );
ElementType DeleteQ( Queue Q );

其中Queue結構定義如下:

typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
    ElementType *Data;  /* 儲存元素的陣列   */
    Position Front;     /* 佇列的頭指標     */
    int Count;          /* 佇列中元素個數   */
    int MaxSize;        /* 佇列最大容量     */
};
typedef PtrToQNode Queue; 

注意:如果佇列已滿,AddQ函式必須輸出“Queue Full”並且返回false;如果佇列是空的,則DeleteQ函式必須輸出“Queue Empty”,並且返回ERROR。

輸入樣例:

4
Del
Add 5
Add 4
Add 3
Del
Del
Add 2
Add 1
Add 0
Add 10
End

輸出樣例:

Queue Empty
5 is out
4 is out
Queue Full
3 2 1 0 

程式碼


#include <stdio.h>
#include <stdlib.h>

#define ERROR -1
typedef int ElementType;
typedef enum { addq, delq, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
    ElementType *Data;  /* 儲存元素的陣列   */
    Position Front;     /* 佇列的頭、尾指標 */
    int Count;          /* 佇列中元素個數   */
    int MaxSize;        /* 佇列最大容量     */
};
typedef PtrToQNode Queue; 

Queue CreateQueue( int MaxSize )
{
    Queue Q = (Queue)malloc(sizeof(struct QNode));
    Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    Q->Front = 0;
    Q->Count = 0;
    Q->MaxSize = MaxSize;
    return Q;
}

bool AddQ( Queue Q, ElementType X );
ElementType DeleteQ( Queue Q );

Operation GetOp();  /* 裁判實現,細節不表 */

int main()
{
    ElementType X;
    Queue Q;
    int N, done = 0;

    scanf("%d", &N);
    Q = CreateQueue(N);
    while ( !done ) {
        switch( GetOp() ) {
        case addq: 
            scanf("%d", &X);
            AddQ(Q, X);
            break;
        case delq:
            X = DeleteQ(Q);
            if ( X!=ERROR ) printf("%d is out\n", X);
            break;
        case end:
            while (Q->Count) printf("%d ", DeleteQ(Q));
            done = 1;
            break;
        }
    }
    return 0;
}

/* 你的程式碼將被嵌在這裡 */
bool AddQ(Queue Q, ElementType X)
{
	if (Q->MaxSize==Q->Count)
	{
		printf("Queue Full\n");
		return ERROR;
	}
	++Q->Count;
	Q->Data[(Q->Front + Q->Count) % Q->MaxSize] = X;
	return true;

}
ElementType DeleteQ(Queue Q)
{
	if (Q->Count==0)
	{
		printf("Queue Empty\n");
		return ERROR;
	}
	--Q->Count;
	Q->Front = (Q->Front + 1) % Q->MaxSize;
	return Q->Data[Q->Front];

}

6-2 雙端佇列 (25分)

雙端佇列(deque,即double-ended queue的縮寫)是一種具有佇列和棧性質的資料結構,即可以(也只能)線上性表的兩端進行插入和刪除。若以順序儲存方式實現雙端佇列,請編寫例程實現下列操作:

Push(X,D):將元素X插入到雙端佇列D的頭;
Pop(D):刪除雙端佇列D的頭元素,並返回;
Inject(X,D):將元素X插入到雙端佇列D的尾部;
Eject(D):刪除雙端佇列D的尾部元素,並返回。

函式介面定義:

bool Push( ElementType X, Deque D );
ElementType Pop( Deque D );
bool Inject( ElementType X, Deque D );
ElementType Eject( Deque D );

其中Deque結構定義如下:

typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
    ElementType *Data;      /* 儲存元素的陣列   */
    Position Front, Rear;   /* 佇列的頭、尾指標 */
    int MaxSize;            /* 佇列最大容量     */
};
typedef PtrToQNode Deque; 

注意:Push和Inject應該在正常執行完操作後返回true,或者在出現非正常情況時返回false。當Front和Rear相等時佇列為空,Pop和Eject必須返回由裁判程式定義的ERROR。

輸入樣例:

3
Pop
Inject 1
Pop
Eject
Push 2
Push 3
Eject
Inject 4
Inject 5
Inject 6
Push 7
Pop
End

輸出樣例:

Deque is Empty!
1 is out
Deque is Empty!
2 is out
Deque is Full!
Deque is Full!
3 is out
Inside Deque: 4 5

程式碼

#include <stdio.h>
#include <stdlib.h>

#define ERROR -1
typedef int ElementType;
typedef enum { push, pop, inject, eject, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode {
    ElementType *Data;      /* 儲存元素的陣列   */
    Position Front, Rear;   /* 佇列的頭、尾指標 */
    int MaxSize;            /* 佇列最大容量     */
};
typedef PtrToQNode Deque; 

Deque CreateDeque( int MaxSize )
{   /* 注意:為區分空佇列和滿佇列,需要多開闢一個空間 */
    Deque D = (Deque)malloc(sizeof(struct QNode));
    MaxSize++;
    D->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    D->Front = D->Rear = 0;
    D->MaxSize = MaxSize;
    return D;
}

bool Push( ElementType X, Deque D );
ElementType Pop( Deque D );
bool Inject( ElementType X, Deque D );
ElementType Eject( Deque D );

Operation GetOp();          /* 裁判實現,細節不表 */
void PrintDeque( Deque D ); /* 裁判實現,細節不表 */

int main()
{
    ElementType X;
    Deque D;
    int N, done = 0;

    scanf("%d", &N);
    D = CreateDeque(N);
    while (!done) {
        switch(GetOp()) {
        case push: 
            scanf("%d", &X);
            if (!Push(X, D)) printf("Deque is Full!\n");
            break;
        case pop:
            X = Pop(D);
            if ( X==ERROR ) printf("Deque is Empty!\n");
            else printf("%d is out\n", X);
            break;
        case inject: 
            scanf("%d", &X);
            if (!Inject(X, D)) printf("Deque is Full!\n");
            break;
        case eject:
            X = Eject(D);
            if ( X==ERROR ) printf("Deque is Empty!\n");
            else printf("%d is out\n", X);
            break;
        case end:
            PrintDeque(D);
            done = 1;
            break;
        }
    }
    return 0;
}

/* 你的程式碼將被嵌在這裡 */

// 頭插
bool Push(ElementType X, Deque D)
{
	// 算尾部位置,如果滿了返回false
	if ((D->Rear + 1) % (D->MaxSize) == D->Front)
		return false;
	// 減完了才能用公式
	D->Front--;
	D->Front = (D->MaxSize + D->Front) % (D->MaxSize);
	D->Data[D->Front] = X;
	return true;
}

// 頭刪
ElementType Pop(Deque D)
{
	if (D->Front == D->Rear)
		return ERROR;
	ElementType d = D->Data[D->Front];
	D->Front++;
	D->Front = D->Front % (D->MaxSize);
	return d;
}

// 尾插
bool Inject(ElementType X, Deque D)
{
    // 算尾部位置,如果滿了返回false
	if ((D->Rear + 1) % (D->MaxSize) == D->Front)
		return false;
	D->Data[D->Rear] = X;
	D->Rear = (D->Rear + 1) % D->MaxSize;
	return true;
}

// 尾刪
ElementType Eject(Deque D)
{
	if (D->Front == D->Rear)
		return ERROR;
	if (!D->Rear)
		D->Rear = D->MaxSize;
	D->Rear--;
	ElementType d = D->Data[D->Rear];
	return d;
}

程式設計題

7-1 堆疊模擬佇列 (25分)

設已知有兩個堆疊S1和S2,請用這兩個堆疊模擬出一個佇列Q。

所謂用堆疊模擬佇列,實際上就是通過呼叫堆疊的下列操作函式:

  • int IsFull(Stack S):判斷堆疊S是否已滿,返回1或0;
  • int IsEmpty (Stack S ):判斷堆疊S是否為空,返回1或0;
  • void Push(Stack S, ElementType item ):將元素item壓入堆疊S;
  • ElementType Pop(Stack S ):刪除並返回S的棧頂元素。

實現佇列的操作,即入隊void AddQ(ElementType item)和出隊ElementType DeleteQ()。

輸入格式:

輸入首先給出兩個正整數N1和N2,表示堆疊S1和S2的最大容量。隨後給出一系列的佇列操作:A item表示將item入列(這裡假設item為整型數字);D表示出隊操作;T表示輸入結束。

輸出格式:

對輸入中的每個D操作,輸出相應出隊的數字,或者錯誤資訊ERROR:Empty。如果入隊操作無法執行,也需要輸出ERROR:Full。每個輸出佔1行。

輸入樣例:

3 2
A 1 A 2 A 3 A 4 A 5 D A 6 D A 7 D A 8 D D D D T

輸出樣例:

ERROR:Full
1
ERROR:Full
2
3
4
7
8
ERROR:Empty

程式碼

模擬佇列

#include<stdio.h>
#include<iostream>
#include<stack>
#include<string>

using namespace std;
stack<int>s1, s2;   //定義兩個棧
int n1, n2;         //兩個棧的容量

int main()
{
	char c;
	int m, p, q;
	cin >> n1 >> n2;
	if (n1 > n2) 
		swap(n1, n2);  // 保證更大的容量的S2作為輸出棧
	getchar();
	while (1) 
	{     
		// 無限迴圈輸入
		cin >> c;
		if (c == 'T') 
			break;     // 輸入字元為T時結束
		if (c == 'A') 
		{
			cin >> m;
			if (s1.size() == n1 && s2.size() != 0)   // 只有當s1為滿,s2不為空時才是滿的情況
				printf("ERROR:Full\n");
			else if (s1.size() == n1 && s2.size() == 0) 
			{   
				// 當s1為滿,s2為空時,先將s1裡面所有的元素轉移到s2,再將新加入的元素放置s1
				q = n1;
				while (q--) 
				{
					p = s1.top();
					s1.pop();
					s2.push(p);
				}
				s1.push(m);
			}
			else if (s1.size() != n1)  // 若s1不滿,可直接將新入的元素放置s1裡面
				s1.push(m);;
		}
		if (c == 'D') 
		{   
			//輸入字元為D時要出隊
			if (s1.size() == 0 && s2.size() == 0)    //只有當s1,s2均為空時才為隊空的情況
				printf("ERROR:Empty\n");
			else if (s1.size() != 0 && s2.size() == 0)
			{  
				//若s2為空,s1不空,則先把s1裡面所有元素轉移至s2,再輸出s2的棧頂元素
				q = s1.size();
				while (q--) {
					p = s1.top();
					s1.pop();
					s2.push(p);
				}
				cout << s2.top() << endl;
				s2.pop();
			}
			else if (s2.size() != 0) 
			{ 
				//如果s2不為空,可直接輸出s2棧頂元素
				cout << s2.top() << endl;
				s2.pop();
			}
		}
	}
	return 0;
}


直接用queue

#include<bits/stdc++.h> 
using namespace std;
queue<int> q; 
  
int main()
{  
    int m,n,i,a;  
    char c;  
    cin>>m>>n;  
    n+=m;	
    for(i=0;;i++)
	{  
        cin>>c;  
        if(c=='T')  
            return 0;
        if(c=='A')
		{  
            cin>>a;  
            if(q.size()==n)
			{
                cout<<"ERROR:Full"<<endl;  
            }  
            else
			{  
                q.push(a);  
            }  
        }  
        else if(c=='D')
		{  
            if(q.size()==0)
			{  
                cout<<"ERROR:Empty"<<endl;  
            }  
            else
			{  
                cout<<q.front()<<endl;  
                q.pop();   
            }  
        }  
    }  
    return 0;  
}

相關文章