数据结构线性表之栈与队列

数据结构线性表之栈与队列

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代码实现

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