数据结构ky备战Day2 - 栈和队列(受限的线性表)

*顺序栈 SeqStack

重点内容:

入栈时判满 S->top == Stack_Size(栈顶指针指向栈顶元素的元素版本)

出栈时判空 S->top == -1

#include<stdio.h>
#include<stdlib.h>
#define StackElemType char
#define OK 1
#define Error -1
#define Stack_Size 50

typedef struct
{
	StackElemType elem[Stack_Size]; /* elem是存放栈中的一维数组 */
	int top; /* 栈顶元素的下标,空栈为-1 */
}SeqStack;

// 基操 1 初始化
void InitStack(SeqStack *S){
	S->top = -1;
}

// 基操2 入栈 注意判满 , 我用的是栈顶指针指向元素的版本
int push(SeqStack *S, StackElemType x)
{
	if(S->top == Stack_Size) return Error; // 栈满
	
	S->top ++ ;
	S->elem[S->top] = x ;
	return OK;
}

// 基操3 出栈 注意判空
int pop(SeqStack *S, StackElemType *x){
	if(S->top == -1) return Error;
	
	*x = S->elem[S->top]; 
	S->top--; 
	return OK;
}

// 基操4 取栈顶元素 注意判空
int getTop(SeqStack S, StackElemType *x){
	if(S.top == -1) return Error;
	
	*x = S.elem[S.top];
	return OK;
}


链栈 LinkStack

没什么好说的,因为就是受限的单链表,所有操作在表头进行了,相当于复习了一下头插法

#include<stdio.h>
#include<stdlib.h>
#define StackElemType char
#define OK 1
#define Error -1
#define Stack_Size 50

// 链栈注意,他是链表中受限的结构,即只允许在表头进行插入和删除操作
typedef struct node
{
	StackElemType data; 
	struct node *next;
}LinkStackNode, *LinkStack;


// 链栈基操1 进栈
int push(LinkStack top, StackElemType x){
	/* 元素x压入栈中,top是头节点 */
	LinkStackNode *temp = (LinkStackNode *)malloc(sizeof(LinkStackNode)); // 申请新结点
	if(temp == NULL) return Error;
	// 头插法插入操作
	temp->data = x;
	temp->next = top->next;
	top->next = temp;
	return OK;
}

// 链栈基操2 出栈
int pop(LinkStack top, StackElemType *x){
	/* 将栈顶元素弹出 存入x存储空间中 */
	LinkStackNode *temp = top->next;
	if(temp == NULL) return Error; // 空栈的情况直接返回错误
	top->next = temp->next;
	*x = temp->data; // 存入x空间
	free(temp); // 释放空间
	return OK;
}


// 注意多栈的概念,Linkstack top[N]

队列

*循环队列 SeqQueue

重点内容

循环队列的出现就是为了解决假溢出

当rear == Maxsize - 1 时 ,队头可能因为出队而产生空单元,但由于只能在队尾插入,因此导致空单元无法使用

队空:Q->rear == Q.front

队满:(Q->rear + 1) % MaxSize == Q->front

元素长度:(Q->rear - Q->front + MaxSize) % MaxSize

#include<stdio.h>
#include<stdlib.h>
#define QueueElemType char
#define OK 1
#define Error -1
#define MAXSIZE 50

typedef struct{
	QueueElemType elem[MAXSIZE];
	int front; // 指向表头
	int rear; // 指向表尾
}SeqQueue;

// 循环队列基操1 初始化
void InitQueue(SeqQueue *Q){
	Q->front = Q->rear = 0;
}

// 循环队列基操2 入队 注意队满的情况
int EnQueue(SeqQueue *Q, QueueElemType x){
	if((Q->rear + 1) % MAXSIZE == Q->front) return Error;
	Q->elem[Q->rear] = x;
	Q->rear = (Q->rear + 1) % MAXSIZE;
	return OK;
}


// 循环队列基操3 出队 注意队空的情况
int DeQueue(SeqQueue *Q, QueueElemType *x){
	if(Q->front == Q->rear) return Error;
	*x = Q->elem[Q->front]; // 队首元素出队
	Q->front = (Q->front + 1) % MAXSIZE;
	return OK;
}

*法二:tag变量来区分队空和队满

tag == 0 时 队空,tag == 1时 队满,此时不必像法一那样空出一个存储空间来判断队空和队满了

注意两点即可。

  • 入队的时候,要注意入队前队空的情况,tag = 0 --- tag =1
  • 出队的时候,要注意出队后队空的情况,tag = 1 --- tag = 0
// 循环队列基操2 入队 注意队满的情况
int EnQueue(SeqQueue *Q, QueueElemType x){
	if(Q->rear == Q->front && tag == 1) return Error;
    if(Q->rear == Q->front && tag == 0) tag = 1; // 队空的情况
	Q->elem[Q->rear] = x;
	Q->rear = (Q->rear + 1) % MAXSIZE;
	return OK;
}


// 循环队列基操3 出队 注意队空的情况
int DeQueue(SeqQueue *Q, QueueElemType *x){
	if(Q->front == Q->rear && tag == 0) return Error;
	*x = Q->elem[Q->front]; // 队首元素出队
	Q->front = (Q->front + 1) % MAXSIZE;
	return OK;
}

链队列 LinkQueue

这个没啥好说,就是链表多了两个指针罢了。其他和单链表差不多,所以也不是考察的核心。

仅当单链表基操的练习

#include<stdio.h>
#include<stdlib.h>
#define QueueElemType char
#define OK 1
#define Error -1
#define Stack_Size 50

typedef struct Node{
	QueueElemType data; 
	struct Node *next;
}LinkQueueNode;

typedef struct{
	LinkQueueNode *front;
	LinkQueueNode *rear;
}LinkQueue;

// 链队列初始化
int initQueue(LinkQueue *Q){
	Q->front = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
	if(Q->front != NULL){
		Q->rear = Q->front;  // 链队列空的条件
		Q->front->next = NULL;
		return OK;
	}
	else return Error; // 溢出
}

// 链队列入队
int EnQueue(LinkQueue *Q, QueueElemType x){
	LinkQueueNode *newNode;
	newNode = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
	if(newNode == NULL) return Error;
	// 尾插法
	newNode->data = x;
	Q->rear->next = newNode; // 注意 表尾在尾部
	Q->rear = newNode;
	return OK;
}

// 链队列出队
int DeQueue(LinkQueue *Q, QueueElemType *x){
	LinkQueueNode *p;
	if(Q->front == Q->rear) return Error; // 判空
	// 头部删除
	p = Q->front->next;
	Q->front->next = p->next;
	*x = p->data;
	free(p);
	return OK;
}

posted @ 2023-10-06 21:52  yuezi2048  阅读(11)  评论(0编辑  收藏  举报