数据结构 (六) 线性表_栈

一. 栈的基本概念

  1. 栈首先也是线性表,只是栈是一个受限的线性表.
  2. 栈具有前驱和后继的关系.
  3. 插入只能插入到栈顶,删除也是
  4. 栈的数据入口和出口相同,都是栈顶,所以栈后进先出

二. 栈的特性

  1. LIFO后进先出
  2. 出栈和入栈只有一个入口,就是栈顶

三. 基于顺序存储的栈结构

① 顺序存储的栈的概念

栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表.顺序栈的存储结构是:利用一组地址连续的内存单元依次存放自栈底到栈顶的数据元素,同时设定top只是栈顶元素在顺序表中的位置

② 顺序存储栈的实现

因为栈是一种特殊的线性表,所以栈的顺序存储可以通过顺序线性表来实现

③ 使用数组模拟栈的顺序存储

栈顶放到数组的后面,这样数据插入的时候,不用频繁的移动

实现部分 SeqStack.h

#pragma once
#include <stdlib.h>
#include <stdio.h>
#define MAX_SIZE  1024
#define SEQ_STACK_TRUE 1
#define SEQ_STACK_FALSE 0

// 使用数组模拟栈操作,栈使用顺序存储来实现
typedef struct SeqStack
{
	void *data[MAX_SIZE];
	int size;
} SeqStack;

// 栈的操作
SeqStack *init_seq_stack();

// 入栈
void push_seq_stack(SeqStack *stack, void *data);

// 出栈
void pop_seq_stack(SeqStack *stack);

// 返回栈顶元素
void *top__seq_stack(SeqStack *stack);

// 判断是否为空
int is_empty(SeqStack *stack);

// 获取栈中元素个数
int get_size(SeqStack *stack);

// 清空栈
void clear_seq_stack(SeqStack *stack);

// 销毁栈
void destroy_seq_stack(SeqStack *stack);

SeqStack.c

#include "SeqStack.h"

// 栈的操作
SeqStack *init_seq_stack()
{
	SeqStack *stack =(SeqStack*) malloc(sizeof(SeqStack));
	// 这里分配内存的时候数组有没有分配内存呢,可以查看一下seqStack的大小
	//printf("sizeof(SeqStack) = %zu\n", sizeof(SeqStack));
	if (stack != NULL)
	{
		// 数组初始化
		for (int i = 0; i < MAX_SIZE; i++)
		{
			stack->data[i] = NULL;
		}
		stack->size = 0;
	}
	return stack;
}

// 入栈
void push_seq_stack(SeqStack *stack, void *data)
{
	if (stack->size == MAX_SIZE)
	{
		return;
	}
	if (stack != NULL && data != NULL)
	{
		stack->data[stack->size] = data;
		stack->size++;
	}
}

// 出栈
void pop_seq_stack(SeqStack *stack)
{
	if (stack != NULL && stack->size > 0)
	{
		stack->data[stack->size - 1] = NULL;
		stack->size--;
	}
}

// 返回栈顶元素
void *top__seq_stack(SeqStack *stack)
{
	if (stack != NULL && stack->size > 0)
	{
		return stack->data[stack->size - 1];
	}
	return NULL;
}

// 判断是否为空
int is_empty(SeqStack *stack)
{
	if (stack != NULL)
	{
		return stack->size == 0 ? SEQ_STACK_TRUE : SEQ_STACK_FALSE;
	}
	return SEQ_STACK_TRUE;
}

// 获取栈中元素个数
int get_size(SeqStack *stack)
{
	if (stack != NULL)
	{
		return stack->size;
	}
	return -1;
}

// 清空栈
void clear_seq_stack(SeqStack *stack)
{
	if (stack != NULL)
	{
		for (int i = 0; i < stack->size; i++)
		{
			stack->data[i] = NULL;
		}
		stack->size = 0;
	}
}

// 销毁栈
void destroy_seq_stack(SeqStack *stack)
{
	if (stack != NULL)
	{
		free(stack);
	}
}

测试代码:

#include "SeqStack.h"

typedef struct Person
{
	char name[64];
	int age;
} Person;


int main()
{
	SeqStack* stack =  init_seq_stack();
	// 创建数据
	Person p1 = { "P1",10 };
	Person p2 = { "P2",20 };
	Person p3 = { "P3",30 };
	Person p4 = { "P4",40 };
	Person p5 = { "P5",50 };

	// 入栈
	push_seq_stack(stack, (void *)&p1);
	push_seq_stack(stack, (void *)&p2);
	push_seq_stack(stack, (void *)&p3);
	push_seq_stack(stack, (void *)&p4);
	push_seq_stack(stack, (void *)&p5);

	// 获取栈顶元素,然后出栈,看看是不是后进先出
	Person *p;
	for (int i = 0; i < 5; i++)
	{
		// 获取栈顶元素,出栈
		p = (Person *)top__seq_stack(stack);
		pop_seq_stack(stack);

		printf("第 %d 个栈顶元素: 姓名: %s 年龄: %d \n", i + 1, p->name, p->age);
	}
	// 打印的顺序: P5,P$,P4,P2,P1

	// 获取栈的大小,因为都出栈了,所以这里的大小为0
	printf("栈的大小: %d\n", stack->size);
	push_seq_stack(stack, (void*)&p1);
	push_seq_stack(stack, (void *)&p2);

	printf("栈的大小: %d\n", stack->size); // 2

	// 清空栈
	clear_seq_stack(stack);
	printf("栈的大小: %d\n", get_size(stack));

	destroy_seq_stack(stack);


	system("pause");
	return 0;
}

结果:

四. 基于链式存储的栈结构

① 链式栈(链栈基本概念)

使用链表实现栈,主要是用单链表,并且插入和删除操作只有一个入口,就是链表的第一个元素.
栈顶top第一个节点,next指向下一个节点,栈底节点的next指向NULL

② 链式栈的实现

LinkStack.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LINK_SATCK_TRUE 1
#define LINK_STACK_FALSE 0

typedef struct LinkNode
{
	struct LinkNode *next;
} LinkNode;


// 链式栈
typedef struct LinkStack
{
	struct LinkNode head;
	int size;
} LinkStack;


// 初始化函数
LinkStack *init_link_stack();

// 入栈
void push_link_stack(LinkStack *stack, LinkNode *data);

// 出栈
void pop_link_stack(LinkStack *stack);

// 返回栈顶元素
LinkNode *top_link_stack(LinkStack *stack);

// 栈是否为空
int is_empty_link_stack(LinkStack *stack);

// 返回栈的大小
int get_size_link_stack(LinkStack *stack);

// 清空栈
void clear_link_stack(LinkStack *stack);

// 销毁栈
void destroy_link_stack(LinkStack *stack);


LinkStack.c

#include "LinkStack.h"
// 初始化函数
LinkStack *init_link_stack()
{
	// 为stack分配内存
	LinkStack *stack = (LinkStack* )malloc(sizeof(LinkStack));
	if (stack != NULL)
	{
		// 将头节点指向空,表示头尾重合没有其他的节点
		stack->head.next = NULL;
		stack->size = 0;
		return stack;
	}
	return NULL;
}

// 入栈
void push_link_stack(LinkStack *stack, LinkNode *data)
{
	// 插入到头部
	// 新节点指向头部的后继节点
	// 头部的后继节点指向新节点
	if (stack != NULL && data != NULL)
	{
		data->next = stack->head.next;
		stack->head.next = data;
		stack->size++;
	}


}

// 出栈
void pop_link_stack(LinkStack *stack)
{
	if (stack != NULL && stack->size > 0)
	{
		// 先找到栈顶元素
		LinkNode *nodeDel = stack->head.next;
		// 将头部指向栈顶元素的下一个节点
		stack->head.next = nodeDel->next;
		stack->size--;
	}
}

// 返回栈顶元素
LinkNode *top_link_stack(LinkStack *stack)
{
	if (stack != NULL && stack->size > 0)
	{
		return stack->head.next;
	}
	return NULL;
}

// 栈是否为空
int is_empty_link_stack(LinkStack *stack)
{
	if (stack != NULL)
	{
		return stack->size == 0 ? LINK_SATCK_TRUE : LINK_STACK_FALSE;
	}
	return LINK_STACK_FALSE;
}

// 返回栈的大小
int get_size_link_stack(LinkStack *stack)
{
	if (stack != NULL)
	{
		return stack->size;
	}
	return -1;
}

// 清空栈
void clear_link_stack(LinkStack *stack)
{
	if (stack != NULL)
	{
		stack->head.next = NULL;
		stack->size = 0;
	}
}

// 销毁栈
void destroy_link_stack(LinkStack *stack)
{
	if (stack != NULL)
	{
		free(stack);
	}
}

测试代码:

#include "LinkStack.h"

typedef struct Person
{
	LinkNode *node;
	char name[64];
	int age;
} Person;


int main()
{
	// 创建Person
	Person p1, p2, p3, p4, p5;
	int arrLen = sizeof(p1.name) / sizeof(p1.name[0]);
	strcpy_s(p1.name, arrLen, "P1");
	strcpy_s(p2.name, arrLen, "P2");
	strcpy_s(p3.name, arrLen, "P3");
	strcpy_s(p4.name, arrLen, "P4");
	strcpy_s(p5.name, arrLen, "P5");

	p1.age = 10;
	p2.age = 20;
	p3.age = 30;
	p4.age = 40;
	p5.age = 50;

	// 创建栈,然后入栈
	LinkStack *stack = init_link_stack();
	push_link_stack(stack, (LinkNode *)&p1);
	push_link_stack(stack, (LinkNode *)&p2);
	push_link_stack(stack, (LinkNode *)&p3);
	push_link_stack(stack, (LinkNode *)&p4);
	push_link_stack(stack, (LinkNode *)&p5);

	Person *p;
	// 出栈,并且打印
	for (int i = 0; i < 5; i++)
	{
		p = (Person *)top_link_stack(stack);
		pop_link_stack(stack);
		printf("第 %d 次,栈顶元素: 姓名: %s, 年龄: %d \n", i + 1, p->name, p->age);
	}

	// 出栈之后的大小为0
	printf("出栈完成之后,栈大小: %d\n", stack->size);

	// 再放入两个节点p1和p2
	push_link_stack(stack, (LinkNode *)&p1);
	push_link_stack(stack, (LinkNode *)&p2);

	// 栈大小为2
	printf("放入两个节点之后的栈大小: %d\n", stack->size);
	p = (Person *)top_link_stack(stack);// 栈顶
	printf("栈顶节点: 姓名: %s,年龄: %d\n", p->name, p->age);

	// 清空栈
	clear_link_stack(stack);
	printf("清空栈之后的栈的大小: %d\n", stack->size);

	destroy_link_stack(stack);
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值