02栈和队列

159 阅读3分钟

一、顺序栈的表示和实现

// 顺序栈的存储结构
#define MAXSIZE 100
typedef int SElemType;
typedef struct {
	SElemType *base;		// 栈底指针
	SElemType *top;			// 栈顶指针
	int stacksize;			// 栈可用的最大容量 
} SqStack;

其中base指针始终指向栈底位置,top指针指向栈顶的位置(栈顶元素的头上)初始值top和base都指向栈底。

顺序栈的初始化

typedef int Status;
Status InitStack(SqStack &S) {
	S.base = (SElemType *)malloc(sizeof(SElemType) * MAXSIZE);	// 将空间分配到base指针上 
	if(S.base) exit(0);		// 存储分配失败 
	S.top = S.base;			// 让头指针指向分配好空间的base
	S.stacksize = MAXSIZE;
	return 1; 
}

入栈 / 压栈

Status Push(SqStack &S, SElemType e) {
	// 插入元素e为新的栈顶元素
	if(S.top - S.base == S.stacksize) return 0;	// 栈满
	*S.top++ = e;		// 元素e入栈,栈顶指针加1
	return 1; 
} 

出栈 / 弹栈

Status Pop(SqStack &S, SElemType &e) {
	// 删除栈顶元素,用e返回其值
	if(S.top == S.base) return 0;	// 栈空
	e = *--S.top;		// 先让top降下来指着栈顶元素,然后赋值给e
	return 0; 
}

取栈顶元素

SElemType GetTop(SqStack S) {
	// 返回栈顶元素,不修改栈顶指针
	if(S.top != S.base)	{		// 栈非空 
		return *(S.top - 1);
	} 
}

二、链栈的表示和实现

// 链栈的存储结构
typedef struct StackNode {
	ElemType data;
	struct StackNode *next;
} StackNode, *LinkStack;

链栈的头部作为栈顶,一路指下去正好是出栈的顺序。为了方便插入和删除,没必要像单链表附加头结点。

链栈的入栈

Status Push(LinkStack &S, SElemType e) {
	// 在栈顶插入元素e
	LinkStack p = (LinkStack)malloc(sizeof(StackNode));
	p->data = e;
	p->next = S;		// 新节点下一位指向头指针
	S = p;				// 头指针移动到新的头指针
	return 1; 
}

链栈的出栈

Status Pop(LinkStack &S, SElemType &e) {
	// 删除栈顶元素,用e返回其值
	if(S == NULL) return 0;			// 栈空
	e = S->data;
	LinkStack p = S; 				// 保存栈顶元素,方便释放空间
	S = S->next;					// 栈顶指针向下移动
	free(p);
	return 1; 
}

取栈顶元素

SElemType GetTop(LinkStack S) {
	// 返回栈顶元素,不修改栈顶指针
	if(S != NULL) {			// 栈非空 
		return S->data;	 
	}
}

三、循环队列---顺序表示和实现

#define MAXQSIZE 100
typedef int QElemType;
typedef struct {
	QElemType *base;	// 存储空间的基地址
	int front;			// 头指针
	int rear;			// 尾指针
} SqQueue;

队列空:Q.front == Q.rear 队列满:(Q.rear + 1) % MAXQSIZE == Q.front

初始化

Status InitQueue(SqQueue &Q) {
	// 构造空队列Q
	Q.base = (QElemType *)malloc(sizeof(QElemType) * MAXQSIZE);
	if(!Q.base) return 0;			// 储存空间分配失败
	Q.front = Q.rear = 0;			// 头指针和尾指针置为0,队列空
	return 1; 
}

求队列长度

int QueLength(SqQueue Q) {
	// 返回队列元素个数,即队列的长度
	return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE; 
}

循环队列的入队

Status EnQueue(SqQueue &Q, QElemType e) {
	// 插入元e为Q的新的队尾元素
	if((Q.rear + 1) % MAXQSIZE == Q.front)
		return 0;		// 队尾指针加1正好到队头,说明堆满
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	return 1; 
}

出队

Status DeQueue(SqQueue &Q, QElemType &e) {
	// 删除Q的队头元素,用e返回其值
	if(Q.front == Q.rear) return 0;		// 队空
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSIZE;	// 队头指针加1
	return 1; 
}

取循环队列的队头元素

SElemType GetHead(SqQueue Q) {
	// 返回Q的对头元素,不修改头指针
	if(Q.front != Q.rear) {		// 队列非空
		return Q.base[Q.front];
	} 
}

四、链队---队列的链式表示和实现

// 队列的链式存储结构
typedef struct QNode {
	QElemType data;
	struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
	QueuePtr front;		// 队头指针
	QueuePtr rear;		// 队尾指针
} LinkQueue;

链队的初始化

Status InitQueue(LinkQueue &Q) {
	// 构造一个空队列Q
	Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
	Q.front->next = NULL;		// 头结点置空
	return 1; 
}

构造的链队是有头结点

入队

Status EnQueue(LinkQueue &Q, QElemType e) {
	// 插入元素e为Q的新队尾元素
	QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
	p->data = e;
	
	p->next = NULL;
	Q.rear->next = p;		//  插入新节点到队尾
	
	Q.rear = p;
	return 1; 
}

出队

Status DeQueue(LinkQueue &Q, QElemType &e) {
	// 删除Q的队头元素,用e返回其值
	if(Q.front == Q.rear) return 0;		// 队列空
	QueuePtr p = Q.front->next;			// p指向队头元素 
	e = p->data;
	Q.front->next = p->next;			// 头结点指向队头的下一个元素
	if(Q.rear == p) Q.rear = Q.front;	// 空队,则尾指针指向头结点
	free(p);
	return 1; 
}

取队头元素

SElemType GetHead(LinkQueue Q) {
	// 返回队头元素,不改变指针
	if(Q.front != Q.rear) {				// 队非空 
		return Q.front->next->data;		// 返回队头元素 
	} 
}