数据结构——栈与队列

1. 创作灵感

在学习了链表之后,可以衍生出另外两个新的数据结构:栈(先进后出的线性表)、队列(先进先出的线性表)。通过几个简单的例子,实现栈和队列,提升数据结构的熟练程度

2. 栈的顺序存储结构及实现

通过数组存储数据,实现先进后出的效果。在实现的过程中要注意,初始化栈顶。

cpp 复制代码
/*栈和队列*/
#define  MAXSIZE 10

typedef int SElemType;
typedef struct 
{
	SElemType data[MAXSIZE];
	int top; //栈顶

}SqStack;

//入栈
Status Push(SqStack* S, SElemType e)
{
	if (S->top == MAXSIZE - 1)
	{
		return ERR;

	}
	S->top++;
	S->data[S->top] = e;
	return OK;


}

//出栈
Status Pop(SqStack *S, SElemType* e)
{
	if (S->top == -1)
	{
		return ERR;

	}
	
	*e=S->data[S->top] ;
	S->top--;

	return OK;


}


int main()
{	//test
	int a = 1, b = 2, c = 3;
	int d, e, f;
	SqStack MYStack;
	MYStack.top = -1;

	Push(&MYStack, a);
	Push(&MYStack, b);
	Push(&MYStack, c);
	Pop(&MYStack, &d);
	Pop(&MYStack, &e);
	Pop(&MYStack, &f);
	printf("%d,%d,%d\n", d, e, f);
	


	return 0;
}

3. 栈的链式存储结构

有的时候栈内的元素的个数是不确定的,为了节约存储空间,我们使用链式结构存储栈,以下是链式栈的实现方式

3.1 链式栈的定义

cpp 复制代码
//首先定义栈的一个节点
typedef struct StackNode
{
	char name[30];//存储数据
	struct StackNode* next;//指向下一个节点

}stacknode,*linkstackptr;

//定义一个结构体表示链式栈
typedef struct LinkStack
{
	linkstackptr top;
	int count;
}LinkStack;

3.2 入栈操作

cpp 复制代码
//链站的入栈操作
Status Push(LinkStack* S, const char* e)
{
	linkstackptr s = (linkstackptr)malloc(sizeof(stacknode));
	strcpy_s(s->name,30,e);//将字符串保存到新节点的数据中
	s -> next = S->top;    //新节点的指向栈
	S->top = s;				//更新栈顶
	S->count++;
	return OK;

}

3.3 出栈操作

cpp 复制代码
//链栈的出栈操作
Status Pop(LinkStack* S, char* e)
{
	linkstackptr p;
	strcpy_s(e, 30, S->top->name);
	p = S->top;
	S->top = S->top->next;
	free(p);
	S->count--;
	return OK;
}

3.4 程序的调用

cpp 复制代码
int main()
{    //test
    LinkStack Mylinkstack;
    char e1[30];
    Push(&Mylinkstack, "zhang san");
    Push(&Mylinkstack, "LI si");
    Push(&Mylinkstack, "wang er");
    Push(&Mylinkstack, "zhao liu");

    Pop(&Mylinkstack, e1);
    printf("%s\n", e1);
    Pop(&Mylinkstack, e1);
    printf("%s\n", e1);
    Pop(&Mylinkstack, e1);
    printf("%s\n", e1);

    return 0;
}

运行结果:

从运行结果看实现了先进后出的顺序。

4.队列的链式结构

队列是为了实现先进先出(FIFO)顺序调用的线性表,在存储元素个数不确定的情况下,为了节约存储空间,同样适合使用链式存储结构去实现。

4.1 队列的定义以及初始化

cpp 复制代码
//定义链式队列的一个节点
typedef struct QNode
{
	char name[30];
	struct QNode* next;
}Qnode, * Qnodeptr;

//定义链式队列
typedef struct
{
	Qnodeptr front, rear;
}LinkQueue;

// 链式队列初始化函数
Status InitQueue(LinkQueue* Q)
{
	// 为头节点分配内存
	Q->front = Q->rear = (Qnodeptr)malloc(sizeof(Qnode));
	if (!Q->front) // 检查头节点内存分配是否成功
	{
		printf("Queue init failed: malloc error!\n");
		return ERR;
	}
	Q->front->next = NULL; // 头节点的next置空,队列初始为空
	return OK;
}

4.2 尾部插入元素

cpp 复制代码
/插入元素e在队尾
Status EnQueue(LinkQueue* Q, const char* e)
{
	Qnodeptr s = (Qnodeptr)malloc(sizeof(Qnode));
	if (!s)
		printf("Error!\n");
	strcpy_s(s->name, 30, e);//将字符串保存到新节点的数据中
	s->next = NULL;
	Q->rear->next = s;
	Q->rear = s;
	return OK;

}

4.3 队头取出元素

cpp 复制代码
//出队
Status ExQueue(LinkQueue* Q, char* e)
{
	Qnodeptr p;//定义一个节点的指针
	if (Q->front == Q->rear)
		return ERR;
	p = Q->front->next;
	strcpy_s(e, 30, p->name);
	Q->front->next = p->next;
	if (Q->rear == p)
		Q->rear = Q->front;
	free(p);
	return OK;

}

4.4 测试调用

cpp 复制代码
int main()
{	
	LinkQueue MyQueue;
	char e1[30];
	if (InitQueue(&MyQueue) != OK)
	{
		return -1; // 初始化失败,直接退出程序
	}


	EnQueue(&MyQueue, "Zhangsan");
	EnQueue(&MyQueue, "Lisi");
	EnQueue(&MyQueue, "Wanger");
	EnQueue(&MyQueue, "Zhaoliu");

	ExQueue(&MyQueue, e1);
	printf("%s\n", e1);
	ExQueue(&MyQueue, e1);
	printf("%s\n", e1);
	ExQueue(&MyQueue, e1);
	printf("%s\n", e1);
	return 0;
}

测试结果:

符合先进先出的顺序

相关推荐
毅炼2 小时前
hot100打卡——day17
java·数据结构·算法·leetcode·深度优先
404未精通的狗2 小时前
(数据结构)二叉树(上)
数据结构
寄存器漫游者3 小时前
数据结构 C语言 顺序栈
java·c语言·数据结构
日拱一卒——功不唐捐3 小时前
循环队列+双端队列(C语言)
c语言·数据结构
hnjzsyjyj4 小时前
洛谷 P3383:线性筛素数 ← 埃氏筛
数据结构·埃氏筛
80530单词突击赢4 小时前
STLVector底层原理与高效运用
数据结构·算法
haluhalu.4 小时前
LeetCode---基础算法刷题指南
数据结构·算法·leetcode
80530单词突击赢4 小时前
C++关联容器深度解析:set/map全攻略
java·数据结构·算法
_F_y4 小时前
链表:重排链表、合并 K 个升序链表、K 个一组翻转链表
数据结构·链表