數據結構線性表之棧與隊列

數據結構線性表之棧與隊列

1.棧

1.1.什麼是棧?

棧:一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作。進行數據插入和刪除操作的一端稱爲棧頂,另一端稱爲棧底。棧中的數據元素遵守後進先出LIFO(Last
In First Out)的原則。

壓棧:棧的插入操作叫做進棧/壓棧/入棧,入數據在棧頂。
出棧:棧的刪除操作叫做出棧。出數據也在棧頂。

棧的圖示
1.2.棧的實現

棧的實現一般可以使用數組或者鏈表實現,相對而言數組的結構實現更優一些。因爲數組在尾上插入數據的代價比較小。

棧的數組實現
棧一般可以分爲:
1.靜態棧:使用定長數組存儲

typedef int STDataType;
#define N 10
typedef struct Stack
{
	STDataType a[N];
	int top; // 棧頂
}Stack; 

2.動態棧:使用動態開闢的數組存儲

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top; // 棧頂
	int capacity; // 容量
}Stack; 

1.3.棧的實現(github鏈接):
棧的實現

1.4.棧的OJ習題

給定一個只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判斷字符串是否有效。OJ鏈接

思路分析:利用棧的後進先出原理。遍歷字符串,當輸入爲" ({[ " 時,入棧;當輸入爲 “]})” 和棧頂元素匹配則出棧,直到遍歷字符串結束,若棧最終爲空則返回 true;如果不匹配則直接結束。

具體代碼如下:

//由於C語言庫中沒有棧,故此處需要棧的實現代碼
bool isValid(char * s){    	
	Stack st;    
	StackInit(&st);    
	while(*s)    
	{        
		if(*s == '[' || *s == '(' || *s == '{')        
		{            
			StackPush(&st, *s);            
			++s;        
		}        
		else        
		{            
			if(StackEmpty(&st) == 1)                
				return false;
                        
			char top = StackTop(&st);            
			StackPop(&st);            
			if(*s == ']' && top == '[')            
			{                
				++s;                
				continue;            
			}
			else if(*s == ')' && top == '(')            
			{                
				++s;                
				continue;            
			}
			else if(*s == '}' && top == '{')            
			{                
				++s;                
				continue;            
			}
            		else            
            		{                
				return false;            
			}        
		}
	}
	bool ret = StackEmpty(&st) == 1;    
	StackDestory(&st);    
	return ret;

2.隊列

2.1.什麼是隊列?

隊列:一種特殊的線性表,只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表。隊列具有先進先出FIFO(First In First Out)的特點。

入隊列:進行插入操作的一端稱爲隊尾
出隊列:進行刪除操作的一端稱爲隊頭

隊列的圖示
2.2.隊列的實現

隊列也可以用數組或者鏈表的結構實現,使用鏈表的結構實現更優,因爲使用數組的結構,出隊列在數組頭上出數據,效率會降低。

在這裏插入圖片描述
隊列的創建

// 鏈式結構
typedef struct QListNode
{
	struct QListNode* pNext;
	QDataType data;
}QNode;

// 隊列的結構
typedef struct Queue
{
	QNode* front;
	QNode* rear;
}Queue; 

2.3.隊列的實現(github鏈接):
隊列的實現

2.4.循環隊列

實際中我們還會使用一種隊列叫循環隊列。如操作系統中的生產者、消費者模型。環形隊列可以使用數組(取模)實現,也可以使用循環鏈表實現。

環形隊列

2.4.1.判斷隊空與隊滿

隊空:Q.rear = Q.front
隊滿:Q.rear + 1 = Q.front

判斷隊空與隊滿
2.4.2.實現循環隊列

設計你的循環隊列實現。 循環隊列是一種線性數據結構,其操作表現基於 FIFO(先進先出)原則並且隊尾被連接在隊首之後以形成一個循環。OJ鏈接

具體代碼如下:

typedef struct {    
	int* _a;    
	int _n;    
	int _front;    
	int _rear;
} MyCircularQueue;


bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);

/** Initialize your data structure here. 
Set the size of the queue to be k. */
MyCircularQueue* myCircularQueueCreate(int k) 
{    
	MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));   
	cq->_a = (int*)malloc(sizeof(int)*(k + 1));    
	cq->_n = k + 1;    cq->_front = cq->_rear = 0;
    	return cq;
}

/** Insert an element into the circular queue. 
Return true if the operation is successful. */
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
	if(myCircularQueueIsFull(obj))        
		return false;
		
    	obj->_a[obj->_rear] = value;    
    	obj->_rear++;    
    	if(obj->_rear == obj->_n)        
    		obj->_rear = 0;
    		
	return true;
}

/** Delete an element from the circular queue. 
Return true if the operation is successful. */
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if(myCircularQueueIsEmpty(obj))        
		return false;
		
	++obj->_front;    
	if(obj->_front == obj->_n)        
		obj->_front = 0;
		
	return true;
}

/** Get the front item from the queue. */
int myCircularQueueFront(MyCircularQueue* obj) {    	
	if(myCircularQueueIsEmpty(obj))        
		return -1;
		
    return obj->_a[obj->_front];
}

/** Get the last item from the queue. */
int myCircularQueueRear(MyCircularQueue* obj) {
	if(myCircularQueueIsEmpty(obj))        
		return -1;
		
	int prevRear = obj->_rear - 1;     
	if (obj->_rear == 0)       
		prevRear = obj->_n - 1;
		        
	return obj->_a[prevRear];
}

/** Checks whether the circular queue is empty or not. */
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {    
	return obj->_front == obj->_rear;
}

/** Checks whether the circular queue is full or not. */
bool myCircularQueueIsFull(MyCircularQueue* obj) {
	int nextRear = obj->_rear + 1;    
	nextRear %= obj->_n;
	
    	return nextRear == obj->_front;
}

void myCircularQueueFree(MyCircularQueue* obj) {    
	free(obj->_a);    
	free(obj);
}

2.5.隊列的OJ習題

1.用隊列實現棧。OJ鏈接

思路分析:用兩個隊列q1和q2,總是保持一個隊列爲空。

1.入棧時向非空的一個隊列push;
2.出棧時,設q1非NULL,則從q1隊頭取元素入隊到q2中,直到q1中剩下一個元素,這個元素即爲棧頂元素。
3.求top直接返回非空隊列的隊尾即可。

2.用棧實現隊列。OJ鏈接

思路分析

入隊:把 pushst中所有的元素移到 popst 中,接着把新元素壓入 pushst。再把 pushst中的元素移到 popst 中,最後把popst中所有的元素彈出。
入隊
出隊:直接從 popst 彈出就可以了,因爲popst 的棧頂元素就是隊列的隊首元素。
出隊
OJ代碼(github鏈接)
OJ代碼實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章