【大话数据结构】特殊线性表:栈与队列

作为线性表的一种,栈和队列都具有两种存储方式,顺序存储和链式存储,链式存储的好处是开始不用担心长度。

栈(stack)

后进先出的线性表。它的特点是只能在表尾(栈顶)进行插入和删除操作。

顺序栈:

【大话数据结构】特殊线性表:栈与队列_第1张图片

typedef int SElemType;   /*数据元素类型假设为int*/
typedef struct  
{
	SElemType data[MAXSIZE];
	int count;     /*用于栈顶指示,从0开始计*/
}SqStack;

/*进栈操作push,出栈操作pop*/
void Push(SqStack *S, SElemType e)
{
	if (S->count == MAXSIZE - 1)  /*栈满*/
		return;
	S->count++;
	S->data[S->count] = e;        /*top先加1,将插入元素给栈顶空间*/
}
void Pop(SqStack *S, SElemType *e)
{
	if (S->count == -1)           /*栈空*/
		return;
	*e = S->data[S->count];		/*先把栈顶元素取出,top再减1*/
	S->count--;
}

链栈:

将栈顶指针和链表的头指针结合;链表就不需要判断“栈满”,只需要申请内存。

【大话数据结构】特殊线性表:栈与队列_第2张图片

/*链栈*/
typedef struct StackNode
{
	SElemType data;
	struct StackNode *next;
}StackNode, *LinkStackPtr;

typedef struct LinkStack
{
	LinkStackPtr top;   /*栈顶放头结点*/
	int count;
}LinkStack;

/*链栈的入栈*/
void Push(LinkStack *S, SElemType e)
{
	LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
	p->data = e;
	p->next = S->top;  /*原来的栈顶给新元素的后继*/
	S->top = p;
	S->count++;
}

/*链栈的出栈*/
void Pop(LinkStack *S, SElemType *e)
{
	LinkStackPtr p;
	if (StackEmpty(*S))
		return;
	*e = S->top->data;
	p = S->top;
	S->top = p->next;
	S->count--;
	free(p);
}


队列(queue)

先进先出的线性表。只允许在一端(队尾)进行插入,另一端(队头)进行删除。

循环队列:

为了解决“假溢出”的问题,一般队列都是循环队列。

为了区别“队满”和“队空”情况,rear 指向队尾元素的后一个位置,把 front=rear 认为是队空,而队满的条件是 (rear+1)%QueueSize=front。(队列还保留一个元素空间)


/*循环队列的顺序存储*/
typedef int QElemType;
typedef struct  
{
	QElemType data[MAXSIZE];
	int front;     /*指示头指针*/
	int rear;      /*指示尾指针.若队列不为空,指向队尾元素的下一个位置*/
}SqQueue;
/*初始化队列*/
void InitQueue(SqQueue *Q)
{
	Q->front = 0;
	Q->rear = 0;
}
/*求队列长度,当前队列元素个数*/
int QueueLength(SqQueue Q)
{
	return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}
/*入队和出队*/
void EnQueue(SqQueue *Q, QElemType e)
{
	if ((Q->rear + 1) % MAXSIZE == Q->front)  /*判断队满*/
		return;
	Q->data[Q->rear] = e;					  /*从队尾插入*/
	Q->rear = (Q->rear + 1) % MAXSIZE;        /*rear指针向后移动,若到边界就转到数组头部*/
}
void DeQueue(SqQueue *Q, QElemType *e)
{
	if (Q->rear == Q->front)				  /*判断队空*/
		return;
	*e = Q->data[Q->front];					  /*队头出元素*/
	Q->front = (Q->front + 1) % MAXSIZE;      /*front指针向后移动*/
}

链队列:

空队列时,front和rear都指向头结点;非空时,front指向头结点,rear指向尾结点(不是队尾后一个位置);链表就不需要判断“队满”,只需要申请内存。


/*链式队列*/
typedef int QElemType;
typedef struct QNode        /*结点结构*/
{
	QElemType data;
	struct QNode *next;
}QNode, *QueuePtr;

typedef struct              /*队列的链表结构*/
{
	QueuePtr front, rear;

}LinkQueue;

/*入队和出队*/
void EnQueue(LinkQueue *Q, QElemType e)
{
	QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
	p->data = e;
	p->next = NULL;
	Q->rear->next = p;
	Q->rear = p;
}
void DeQueue(LinkQueue *Q, QElemType *e)
{
	QueuePtr p;
	if (Q->front == Q->rear)  /*因为front是头结点,而不是第一个结点*/
		return;
	p = Q->front->next;
	*e = p->data;
	Q->front->next = p->next;
	if (p = Q->rear)		  /*如果只有一个元素*/
		Q->rear = Q->front;   /*将队尾指向头指针,不能反了*/
	free(p);
}



你可能感兴趣的:(数据结构与算法,c语言,数据结构,栈,队列)