受限线性表--栈

目录

一、栈的基本概念

二、栈的顺序存储

三、栈的链式存储


C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

一、栈的基本概念

  • 概念:

       首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底

  • 特性

     它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。

操作:

1、栈的插入操作,叫做进栈,也成压栈。类似子弹入弹夹(如下图所示)

2、栈的删除操作,叫做出栈,也有的叫做弾栈,退栈。如同弹夹中的子弹出夹(如下图所示)

二、栈的顺序存储

  • 基本概念

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

  • 设计与实现

        利用数组来模拟栈的存储过程。数组首地址做栈底,有利于栈顶频繁做入栈和出栈操作,对于数组尾部做插入删除效率高。

代码如下:

SeqStack.h

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define  MAX  1024

struct SStack {
	void* data[MAX];  //栈的数组

	int m_size;  //栈大小
};

typedef void* SeqStack;

//初始化栈
SeqStack init_SeqStack();

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

//出栈
void pop_SeqStack(SeqStack stack);

//返回栈顶
void * top_SeqStack(SeqStack stack);

//返回栈大小
int size_SeqStack(SeqStack stack);

//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack);

//销毁栈
void destroy_SeqStack(SeqStack stack);

SeqStack.c

#include "SeqStack.h"

//初始化栈
SeqStack init_SeqStack()
{
	struct SStack * MyStack = malloc(sizeof(struct SStack));
	if (MyStack == NULL)
	{
		return NULL;
	}

	//初始化数组
	memset(MyStack->data, 0, sizeof(void*)*MAX);
	//初始化栈大小
	MyStack->m_size = 0;

	return MyStack;
}

//入栈
void push_SeqStack(SeqStack stack , void * data)
{
	//入栈本质 -- 数组尾插
	if (stack == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}
	
	struct SStack * MyStack = stack;
	if (MyStack->m_size == MAX)
	{
		return;
	}

	MyStack->data[MyStack->m_size] = data;
	MyStack->m_size++;
}

//出栈
void pop_SeqStack(SeqStack stack)
{
	//出栈本质 -- 数组尾删
	if (stack == NULL)
	{
		return;
	}
	struct SStack * MyStack = stack;
	if (MyStack->m_size == 0)
	{
		return;
	}

	MyStack->data[MyStack->m_size - 1] = NULL;
	MyStack->m_size--;
}

//返回栈顶
void * top_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}
	struct SStack * MyStack = stack;
	if (MyStack->m_size == 0)
	{
		return NULL;
	}

	return MyStack->data[MyStack->m_size - 1];
}

//返回栈大小
int size_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct SStack * MyStack = stack;

	return MyStack->m_size ;
}

//判断栈是否为空
int isEmpty_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1; //空栈
	}

	struct SStack * MyStack = stack;

	if (MyStack->m_size == 0)
	{
		return 1; //空栈
	}
	return 0; //返回0 代表 不是空栈
}

//销毁栈
void destroy_SeqStack(SeqStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	free(stack);
	stack = NULL;
}

main.c

#include "SeqStack.h"

struct Person {
	char name[128];
	int age;
};

int main(void)
{
	//创建数据
	struct Person p1 = { "aaa", 10 };
	struct Person p2 = { "bbb", 20 };
	struct Person p3 = { "ccc", 30 };
	struct Person p4 = { "ddd", 40 };
	struct Person p5 = { "eee", 50 };

	//初始化栈
	SeqStack myStack = init_SeqStack();

	//入栈
	push_SeqStack(myStack, &p1);
	push_SeqStack(myStack, &p2);
	push_SeqStack(myStack, &p3);
	push_SeqStack(myStack, &p4);
	push_SeqStack(myStack, &p5);

	printf("栈的元素个数为:%d\n", size_SeqStack(myStack));

	while (isEmpty_SeqStack(myStack) == 0)
	{
		struct Person * p = top_SeqStack(myStack);
		printf("姓名:%s 年龄:%d\n", p->name, p->age);

		//出栈
		pop_SeqStack(myStack);
	}

	printf("栈的元素个数为:%d\n", size_SeqStack(myStack));

	//销毁栈
	destroy_SeqStack(myStack);

	system("pause");
	return EXIT_SUCCESS;
}

三、栈的链式存储

  • 设计与实现

      利用链表模拟出  先进后出的数据结构。头节点端做栈顶比较方便做入栈和出栈。

代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//节点结构体
struct stackNode
{
	struct stackNode * next;
};

//栈的结构体
struct LStack
{
	struct stackNode  pHeader;
	int m_size;
};

typedef void * LinkStack;

//初始化
LinkStack init_LinkStack()
{
	struct LStack * myStack = malloc(sizeof( struct LStack));

	if (myStack == NULL)
	{
		return NULL;
	}
	myStack->pHeader.next = NULL;
	myStack->m_size = 0;

	return myStack;
}
//入栈
void push_LinkStack( LinkStack stack , void * data)
{
	//入栈本质 --- 链表头插
	if (stack == NULL)
	{
		return;
	}

	if (data == NULL)
	{
		return;
	}

	struct LStack * myStack = stack;

	//将用户数据 取出前4字节用
	struct stackNode * myNode = data;

	//更改指针指向
	myNode->next = myStack->pHeader.next;
	myStack->pHeader.next = myNode;

	//更新链表长度
	myStack->m_size++;

}

//出栈
void pop_LinkStack(LinkStack stack)
{
	//出栈本质 --- 链表头删
	if (stack == NULL)
	{
		return;
	}

	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return;
	}

	//更改指针指向
	//缓存第一个有数据节点
	struct stackNode * pFirst = myStack->pHeader.next;

	myStack->pHeader.next = pFirst->next;

	//更新栈大小
	myStack->m_size--;

}

//返回栈顶元素
void * top_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return NULL;
	}
	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return NULL;
	}

	return myStack->pHeader.next;

}

//返回栈个数
int size_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct LStack * myStack = stack;

	return myStack->m_size;
}

//判断是否为空
int isEmpty_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return -1;
	}
	struct LStack * myStack = stack;

	if (myStack->m_size == 0)
	{
		return 1;
	}

	return 0;
}
//销毁
void destroy_LinkStack(LinkStack stack)
{
	if (stack == NULL)
	{
		return;
	}
	free(stack);
	stack = NULL;
}




//测试
struct Person
{
	void * node;
	char name[64];
	int age;
};

void test01()
{
	//初始化栈
	LinkStack myStack = init_LinkStack();

	//创建数据
	struct Person p1 = { NULL, "aaa", 10 };
	struct Person p2 = { NULL, "bbb", 20 };
	struct Person p3 = { NULL, "ccc", 30 };
	struct Person p4 = { NULL, "ddd", 40 };
	struct Person p5 = { NULL, "eee", 50 };

	//入栈
	push_LinkStack(myStack, &p1);
	push_LinkStack(myStack, &p2);
	push_LinkStack(myStack, &p3);
	push_LinkStack(myStack, &p4);
	push_LinkStack(myStack, &p5);

	printf("链式存储-- 栈的元素个数为:%d\n", size_LinkStack(myStack));

	while (isEmpty_LinkStack(myStack) == 0) //栈不为空,查看栈顶元素,出栈
	{
		struct Person * p = top_LinkStack(myStack);
		printf("姓名:%s 年龄:%d\n", p->name, p->age);

		//出栈
		pop_LinkStack(myStack);
	}

	printf("链式存储-- 栈的元素个数为:%d\n", size_LinkStack(myStack));

	//销毁栈
	destroy_LinkStack(myStack);
}
int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值