数据结构 栈与队列

栈与队列



栈:线性存储结构;先进后出;开口端为栈顶,封口段为栈底。
相关操作:进栈(压栈或者入栈),即为往里面存数据;出栈(弹栈);
相关实现方法:1.顺序栈;2.链栈。
1.顺序栈
利用数组存储数据,进栈操作和出栈操作和数组的数据存储和输出方法是一样的,而为了出栈操作所以才定义了一个top变量,top最初指向栈顶元素,此时top=-1,需要进栈时top+1,向数组存入一个数据,需要出栈时top-1,从数组中输出一个数据,当top=-1时,就表示此时为空栈,没有存储任何数据,下面看c代码。

#include<stdio.h>
#include<stdlib.h>

int top = -1;//我这里把top和stack数组定义为了全局变量,比较直观
int stack[100000];

//入栈n个数据,然后依次出栈

void push(int data)
{
	top++;
	stack[top] = data;
}

void pop()
{
	if (top == -1)
	{
		printf("空栈,无数据元素\n");
	}
	else
	{
		printf("出栈元素:%d\n", stack[top]);
		top--;
	}
}

int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &stack[i]);
		push(stack[i]);
	}
	for (int i = 1; i <= n + 1; i++)
	{
		pop();
	}
	return 0;
}

2.链栈
链栈当然就是用链表来表示栈的基本操作了,依据栈是“先进后出”的原则,我们用头插法来建立链表,将链表头部作为栈顶,这样避免大量入栈出栈的循环操作。
出栈操作:
1.判断栈顶是否为空
2.输出数据
3.释放节点

#include<stdio.h>
#include<stdlib.h>

typedef struct stack
{
	int data;
	struct stack* next;
}stack;

stack* Push(stack* s, int data)
{
	stack* p;
	p = (stack*)malloc(sizeof(stack));
	p->data = data;
	p->next = s;
	s = p;
	return s;
}
stack* Pop(stack* s)
{
	if (s)
	{
		stack* p = s;
		s = s->next;
		printf("出栈元素:%d\n", p->data);
		if (s)
		{
			printf("此时栈顶元素:%d\n", s->data);
		}
		else
		{
			printf("栈已空\n");
		}
		free(p);
	}
	else
	{
		printf("栈内没有元素\n");
		return s;
	}
	return s;
}//if语句是为了判断栈是否为空,防止栈空的时候输出数据
int main()
{
	stack* s = NULL;
	int n, m;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &m);
		s = Push(s, m);
	}
	for (int i = 0; i <= n; i++)
	{
		s = Pop(s);
	}
	return 0;
}

队列
队列:线性存储结构,先进先出原则,一端进,另一端出。进数据端叫队尾,出数据端叫队头。
队列操作:入队与出队,这是我们会定义两个变量top和rear初始时分别指向队头和队尾,进数据时rear+1,出数据时top+1。
实现方法:1.顺序队列;2.链队列
1.顺序队列
还是用数组来操作,下面看原始操作方法

#include<stdio.h>
#include<stdlib.h>

int top, rear;
int q[100000];

void pushQueue(int data)
{
	q[rear] = data;
	rear++;
}
void popQueue()
{
	if (rear == top)
	{
		printf("队列已空\n");
	}
	else
	{
		printf("出队元素:%d\n", q[top]);
		top++;
	}
}
int main()
{
	int n, m;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &m);
		pushQueue(m);
	}
	for (int i = 0; i <= n; i++)
	{
		popQueue();
	}
	return 0;
}

通过上面的代码我们发现两个问题:
1.我们为数组申请的存储空间使用过后将无法再进行使用,造成浪费;
2.若我们为数组申请的空间不够大时,会造成数组元素溢出。
再看改良方法(转自c语言中文网),我们把数组形成了一个环形表的结构…

#include <stdio.h>
#define max 5//表示顺序表申请的空间大小
int enQueue(int *a,int front,int rear,int data){
    //添加判断语句,如果rear超过max,则直接将其从a[0]重新开始存储,如果rear+1和front重合,则表示数组已满
    if ((rear+1)%max==front) {
        printf("空间已满");
        return rear;
    }
    a[rear%max]=data;
    rear++;
    return rear;
}
int  deQueue(int *a,int front,int rear){
    //如果front==rear,表示队列为空
    if(front==rear%max) {
        printf("队列为空");
        return front;
    }
    printf("%d ",a[front]);
    //front不再直接 +1,而是+1后同max进行比较,如果=max,则直接跳转到 a[0]
    front=(front+1)%max;
    return front;
}
int main() {
    int a[max];
    int front,rear;
    //设置队头指针和队尾指针,当队列中没有元素时,队头和队尾指向同一块地址
    front=rear=0;
    //入队
    rear=enQueue(a,front,rear, 1);
    rear=enQueue(a,front,rear, 2);
    rear=enQueue(a,front,rear, 3);
    rear=enQueue(a,front,rear, 4);
    //出队
    front=deQueue(a, front, rear);
    //再入队
    rear=enQueue(a,front,rear, 5);
    //再出队
    front=deQueue(a, front, rear);
    //再入队
    rear=enQueue(a,front,rear, 6);
    //再出队
    front=deQueue(a, front, rear);
    front=deQueue(a, front, rear);
    front=deQueue(a, front, rear);
    front=deQueue(a, front, rear);
    return 0;
}

2.链队列
定义两个指针top和rear分别指向队头和队尾,尾插法建立链表,之后进入出队操作
出队操作:
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>

typedef struct queue
{
	int data;
	struct queue* next;
}queue;

queue* initQueue()//创建头节点
{
	queue* head = (queue*)malloc(sizeof(queue));
	head->next = NULL;
	return head;
}

queue* puchQueue(queue* rear, int data)
{
	queue* p = (queue*)malloc(sizeof(queue));
	p->data = data;
	p->next = NULL;
	rear->next = p;
	rear = p;
	return rear;
}

queue* popQueue(queue* top,queue* rear)
{
	if (top->next == NULL)
	{
		printf("空队列\n");
		return rear;
	}
	else
	{
		queue* p = top->next;
		printf("出队元素:%d\n", p->data);
		top->next = p->next;
		if (rear == p)
		{
			rear = top;
		}
		free(p);
		return rear;
	}
}

int main()
{
	queue* top, * rear, * queue;//这里面的queue就是建立的头节点,方便以下的操作
	queue = top = rear = initQueue();
	int n, m;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &m);
		rear = puchQueue(rear, m);
	}
	for (int i = 0; i <= n; i++)
	{
		rear = popQueue(top, rear);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值