Day 64 栈的顺序和链式存储 队列

本文介绍了栈和队列这两种数据结构,详细阐述了它们的基本概念、特性以及在顺序存储和链式存储结构下的操作。通过示例代码展示了如何在C语言中实现栈和队列的插入、删除、查看栈顶队头元素等基本操作。同时,讨论了栈的后进先出(LIFO)和队列的先进先出(FIFO)原则。
摘要由CSDN通过智能技术生成

1.栈的概念:

栈( stack )又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新 元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶 元素删除掉,使其相邻的元素成为新的栈顶元素。
Stack ):是只允许在一端进行插入或删除的线性表。首先栈是一 种线性表, 但限定这种线性表只能在某一端进行插入和删除操作。
栈顶 Top ):线性表允许进行插入删除的那一端。
栈底 Bottom ):固定的,不允许进行插入和删除的另一端。
空栈 :不含任何元素的空表。
栈又称为后进先出( Last In First Out )的线性表,简称 LIFO 结构
特性:
它的特殊之处在于限制了这个线性表的插入和删除的位置 , 它始终只在栈顶进行。这也就使
: == 栈底是固定的 , 最先进栈的只能在栈底 ==
对栈的操作:
示例如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_SIZE 50

typedef struct{
	void *data[MAX_SIZE];
	int size;
}Stack;

typedef struct{
	char name[15];
	int age;
	char breed[10]; 
}Stu;

Stack *initstack(void){
	Stack *stack=(Stack *)malloc(sizeof(Stack));
	if(stack==NULL){
		printf("malloc error.\n");
		return NULL;
	}
	for(int i=0;i<MAX_SIZE;i++){
		stack->data[i]=NULL;
	}
	stack->size=0;
	return stack;
}

void pushstack(Stack *stack,void *data){
	if(stack==NULL){
		return;
	}
	if(stack->size==MAX_SIZE){
		return;
	}
	if(data==NULL){
		return;
	}
	stack->data[stack->size]=data;
	stack->size++;
} 

void popstack(Stack *stack){
	if(stack==NULL){
		return;
	}
	if(stack->size==0){
		return;
	}
	stack->data[stack->size-1]=NULL;
	stack->size--;
}

void *topelement(Stack *stack){
	if(stack==NULL){
		return NULL;
	}
	if(stack->size==0){
		return NULL;
	}
	return stack->data[stack->size-1];
}

int isempty(Stack *stack){
	if(stack==NULL){
		return 0;
	}
	if(stack->size==0){
		return 0;
	}
	return 1;
}

int sizestack(Stack *stack){
	if(stack==NULL){
		return -1;
	}
	return stack->size;
}

void clearstack(Stack *stack){
	if(stack==NULL){
		return;
	}
	for(int i=0;i<stack->size;i++){
		stack->data[i]=NULL;
	}
	stack->size=0;
}

void freestack(Stack *stack){
	if(stack==NULL){
		return;
	}
	free(stack);
}

int main(){
	Stack *stack=initstack();
	Stu p1={"洛羽晨",18,"人类"};
	Stu p2={"虚构康",20,"不详"};
	Stu p3={"丁真",23,"出生"};
	Stu p4={"谷爱凌",22,"剑冢"};
	pushstack(stack,&p1);
	pushstack(stack,&p2);
	pushstack(stack,&p3);
	pushstack(stack,&p4);
	while(sizestack(stack)>0){
		Stu *p=(Stu *)topelement(stack);
		printf("name:%s,age=%d,breed=%s\n",p->name,p->age,p->breed);
		popstack(stack);
	}
	freestack(stack);
	return 0;
}

2.栈的链式存储结构:

概念:上面讲的是栈的顺序存储结构,相当于一个线性表,只是操作位置有限制。链式存储结构也就是链表形式的栈。它和链表的结构是一样的,操作方式和上面的一样。

操作:

示例如下:


#include "linkstack.h"
typedef struct
{
char name[64];
int age;
int score;
}Person;
//打印函数
void my_print(void *data)
{
Person *p=(Person *)data;
printf("name:%s age:%d score:%d\n",p->name,p->age,p->score);
}
int main()
{
//创建链表
LinkStack *stack=init_linkstack();
//获取链表长度
printf("stack 长度:%d\n",size_linkstack(stack));
//创建数据
//创建数据
Person p1={"aaa",10,80};
Person p2={"bbb",11,81};
Person p3={"ccc",12,82};
Person p4={"ddd",13,83};
//入栈
push_linkstack(stack, &p1);
push_linkstack(stack, &p2);
//打印
print_linkstack(stack, my_print);
printf("\n");
//入栈
push_linkstack(stack, &p3);
push_linkstack(stack, &p4);
//打印
print_linkstack(stack, my_print);
printf("\n");
//出栈
void *data=pop_linkstack(stack);
my_print(data);
printf("\n");
//打印
print_linkstack(stack, my_print);
printf("\n");
//获取链表长度
printf("stack 长度:%d\n",size_linkstack(stack));
//返回第一个结点
Person *p=(Person *)top_element(stack);
printf("top_element:name-%s,age-%d,score-%d\n",p->name,p->age,p->score);
//销毁
free_linkstack(stack);
return 0;
}
#include "linkstack.h"
//初始链表
LinkStack *init_linkstack(void)
{
LinkStack *stack=(LinkStack *)malloc(sizeof(LinkStack));
stack->size=0;
//头结点
stack->head=(LinkNode *)malloc(sizeof(LinkNode));
stack->head->data=NULL;
stack->head->next=NULL;
return stack;
}
//指定位置插入
void push_linkstack(LinkStack *stack, void *data)
{
if(stack == NULL)
{
return ;
}
if(data == NULL)
{
return ;
}
//创建新的结点
LinkNode *newnode=(LinkNode *)malloc(sizeof(LinkNode));
newnode->data=data;
newnode->next=NULL;
//找结点
//辅助指针变量
LinkNode *pcurrent=stack->head;
//新结点插入链表
newnode->next=pcurrent->next;
pcurrent->next=newnode;
stack->size++;
}
//删除指定位置的值
void *pop_linkstack(LinkStack *stack)
{
if(stack == NULL)
{
return NULL;
}
//找结点
//辅助指针变量
LinkNode *pcurrent=stack->head;
//删除结点
LinkNode *delnode=pcurrent->next;
pcurrent->next=delnode->next;
void *data=delnode->data;
free(delnode);
stack->size--;
return data;
}
//获取链表长度
int size_linkstack(LinkStack *stack)
{
return stack->size;
}
//返回栈顶元素数据域
void *top_element(LinkStack *stack)
{
return stack->head->next->data;
}
//打印栈内所有内容
void print_linkstack(LinkStack *stack, printlinknode print)
{
if(stack == NULL)
{
return ;
}
//辅助指针变量
LinkNode *pcurrent=stack->head->next;
while(pcurrent!=NULL)
{
print(pcurrent->data);
pcurrent=pcurrent->next;
}
}
//释放链表内存
void free_linkstack(LinkStack *stack)
{
if(stack == NULL)
{
return ;
}
//辅助指针变量
LinkNode *pcurrent=stack->head;
while(pcurrent!=NULL)
{
//缓存下一个结点
LinkNode *pnext=pcurrent->next;
free(pcurrent);
pcurrent=pnext;
}
//释放链表内存
stack->size=0;
free(stack);
}
#ifndef LINKLIST_H
#define LINKLIST_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#endif
//结点结构体
typedef struct NODE
{
void *data;
struct NODE *next;
}LinkNode;
//栈表结构体
typedef struct
{
LinkNode *head;
int size;
}LinkStack;
//打印函数指针
typedef void(*printlinknode)(void *);
//初始栈表
LinkStack *init_linkstack(void);
//入栈
void push_linkstack(LinkStack *stack, void *data);
//出栈
void *pop_linkstack(LinkStack *stack);
//获取链表长度
int size_linkstack(LinkStack *stack);
//返回第一个结点
void *top_element(LinkStack *stack);
//打印栈内结点
void print_linkstack(LinkStack *stack, printlinknode print);
//释放栈内存
void free_linkstack(LinkStack *stack);

2.队列的概念:

队列是一种特殊的 线性表 ,特殊之处在于它只允许在表的前端( front )进行删除操作,而在表的后端( rear )进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进 行删除操作的端称为队头。

 

队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中 删除, == 故队列又称为先进先出( FIFO—first in first out 线性表
2.对队列的操作: 增删改查
示例如下:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1024
typedef struct
{
void *data[MAX_SIZE];
int size;
}Queue;
//初始化
Queue * init_queue(void)
{
Queue *queue=(Queue *)malloc(sizeof(Queue));
for(int i=0;i<MAX_SIZE;i++)
{
queue->data[i]=NULL;
}
queue->size=0;
return queue;
}
//入队
void push_queue(Queue *queue, void *data)
{
//数组左边当做对头
if(queue==NULL)
{
return ;
}
if(data==NULL)
{
return ;
}
queue->data[queue->size]=data;
queue->size++;
}
//返回对头元素
void *front_queue(Queue *queue)
{
if(queue==NULL)
{
return NULL;
}
if(queue->size==0)
{
return NULL;
}
return queue->data[0];
}
//出队
void pop_queue(Queue *queue)
{
//需要移动元素
if(queue==NULL)
{
return ;
}
if(queue->size==0)
{
return ;
}
for(int i=0;i<queue->size-1;i++)
{
queue->data[i]=queue->data[i+1];
}
queue->size--;
}
//返回队尾元素
void *back_queue(Queue *queue)
{
if(queue==NULL)
{
return NULL;
}
if(queue->size==0)
{
return NULL;
}
return queue->data[queue->size-1];
}
//返回大小
int size_queue(Queue *queue)
{
if(queue==NULL)
{
return -1;
}
return queue->size;
}
//清空队列
void clear_queue(Queue *queue)
{
if(queue==NULL)
{
return ;
}
while(queue->size>0)
{
queue->size--;
queue->data[queue->size]=NULL;
}
}
//销毁
void free_queue(Queue *queue)
{
if(queue==NULL)
{
return ;
}
free(queue);
}
typedef struct
{
char name [64];
int age;
}Person;
int main()
{
//创建队列
Queue *queue=init_queue();
//创建数据
Person p1={"aaa",10};
Person p2={"bbb",10};
Person p3={"ccc",10};
Person p4={"ddd",10};
//入队
push_queue(queue,&p1);
push_queue(queue,&p2);
push_queue(queue,&p3);
push_queue(queue,&p4);
//取出对尾元素
Person *p=(Person *)back_queue(queue);
printf("name:%s, age=%d\n",p->name,p->age);
printf("\n");
clear_queue(queue);
printf("\n");
//入队
push_queue(queue,&p1);
push_queue(queue,&p2);
push_queue(queue,&p3);
push_queue(queue,&p4);
//输出
while(size_queue(queue)>0)
{
//取出对头元素
Person *p=(Person *)front_queue(queue);
printf("name:%s, age=%d\n",p->name,p->age);
//出队
pop_queue(queue);
}
//销毁队列
free_queue(queue);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值