Stack基本概念

栈是一种 特殊的线性表

栈仅能在线性表的一端进行操作

栈顶(Top):允许操作的一端

栈底(Bottom):不允许操作的一端

Stack的常用操作

创建栈

销毁栈

清空栈

进栈

出栈

获取栈顶元素

获取栈的大小

栈模型和链表模型关系分析

栈的顺序存储设计与实现

// seqlist.h
// 顺序存储结构线性表的API声明

#ifndef  __MY_SEQLIST_H__
#define __MY_SEQLIST_H__

typedef void SeqList;
typedef void SeqListNode;

//链表 创建
SeqList* SeqList_Create(int capacity);

//链表 销毁
void SeqList_Destroy(SeqList* list);

////链表 清空
void SeqList_Clear(SeqList* list);

//链表 长度
int SeqList_Length(SeqList* list);

//链表 容量
int SeqList_Capacity(SeqList* list);

//链表 在某一个位置 插入元素
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

//获取某一个位置的链表结点
SeqListNode* SeqList_Get(SeqList* list, int pos);

//删除某一个位置的结点
SeqListNode* SeqList_Delete(SeqList* list, int pos);

#endif  //__MY_SEQLIST_H__
// seqList.cpp
// 顺序存储结构的栈API实现

#include <iostream>
#include <cstdio>
#include "seqlist.h"

using namespace std;

typedef struct _tag_SeqList
{
	int capacity;
	int length;
	int **node;
}TSeqList;

//链表 创建
SeqList* SeqList_Create(int capacity)
{
	int ret = -1;
	TSeqList *tmp = NULL;
	tmp = (TSeqList *)malloc(sizeof(TSeqList));
	if (tmp == NULL) {
		ret = 1;
		printf("function SeqList_Create() err:%d\n", ret);
		return NULL;
	}
	memset(tmp, 0, sizeof(TSeqList));
	tmp->capacity = capacity;
	tmp->length = 0;
	tmp->node = (int **)malloc(sizeof(void *) * capacity);
	if (tmp->node == NULL) {
		ret = 2;
		printf("function SeqList_Create() err:%d\n", ret);
		return NULL;
	}
	memset(tmp->node, 0, sizeof(void *) * capacity);

	return tmp;
}

//链表 创建
int SeqList_Create2(int capacity, SeqList**handle)
{
	int			ret = 0;
	TSeqList	*tmp = NULL;
	tmp = (TSeqList *)malloc(sizeof(TSeqList));
	if (tmp == NULL)
	{
		ret = 1;
		printf("func SeqList_Create2() err :%d \n", ret);
		return ret;
	}
	memset(tmp, 0, sizeof(TSeqList));
	tmp->capacity = capacity;
	tmp->length = 0;
	tmp->node = (int **)malloc(sizeof(void *) * capacity);
	if (tmp->node == NULL)
	{
		ret = 2;
		printf("func SeqList_Create2() malloc err :%d \n", ret);
		return ret;
	}

	*handle = tmp;
	return ret;
}

//链表 销毁
void SeqList_Destroy(SeqList* list)
{
	if (list == NULL) {
		return;
	}

	TSeqList *tmp = (TSeqList *)list;
	if (tmp->node != NULL) {
		free(tmp->node);
	}
	free(tmp);

	return;
}

////链表 清空
void SeqList_Clear(SeqList* list)
{
	if (list == NULL) {
		return;
	}

	TSeqList *tmp = (TSeqList *)list;
	tmp->length = 0;
	memset(tmp->node, 0, sizeof(tmp->node));

	return;
}

//链表 长度
int SeqList_Length(SeqList* list)
{
	if (list == NULL) {
		return -1;
	}

	TSeqList *tmp = (TSeqList *)list;
	return tmp->length;
}

//链表 容量
int SeqList_Capacity(SeqList* list)
{
	if (list == NULL) {
		return -1;
	}

	TSeqList *tmp = (TSeqList *)list;
	return tmp->capacity;
}

//链表 在某一个位置 插入元素
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
	if (list == NULL || node == NULL || pos < 0) {
		return -1;
	}

	TSeqList *tList = (TSeqList *)list;

	// 如果满了
	if (tList->length >= tList->capacity) {
		return -2;
	}

	// 如果pos的位置超出了length,即中间空了一些位置
	if (pos > tList->length) {
		pos = tList->length;
	}

	for (int i = tList->length; i > pos; --i) {
		tList->node[i] = tList->node[i - 1];
	}
	tList->node[pos] = (int *)node;
	++tList->length;

	return 0;
}

//获取某一个位置的链表结点
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
	TSeqList *tList = (TSeqList *)list;
	if (list == NULL || pos < 0 || pos >= tList->length)
	{
		return NULL;
	}

	SeqListNode *tListNode = NULL;
	tListNode = (int *)tList->node[pos];

	return tListNode;
}

//删除某一个位置的结点
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
	TSeqList *tList = (TSeqList *)list;
	SeqListNode *tListNode = NULL;
	if (list == NULL || pos < 0 || pos >= tList->length) {
		return NULL;
	}

	tListNode = tList->node[pos];
	for (int i = pos + 1; i < tList->length; ++i) {
		tList->node[i - 1] = tList->node[i];
	}
	--tList->length; // 别忘了长度减一

	return tListNode;
}
// seqstack.h
// 顺序存储结构的栈API声明

#ifndef __SEQSTACK_H__
#define __SEQSTACK_H__

typedef void SeqStack;

// 创建栈
SeqStack* SeqStack_Create(int capacity);

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

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

// 元素入栈
int SeqStack_Push(SeqStack* stack, void* item);

// 弹出栈顶元素
void* SeqStack_Pop(SeqStack* stack);

// 获取栈顶元素
void* SeqStack_Top(SeqStack* stack);

// 获取栈的大小
int SeqStack_Size(SeqStack* stack);

// 获取栈的容量
int SeqStack_Capacity(SeqStack* stack);

#endif
// seqstack.cpp
// 顺序存储结构栈的API实现
// 调用了之前写好的顺序链表API

#include <cstdio>
#include "seqlist.h"
#include "seqstack.h"

// 创建栈,相当于创建一个线性表
SeqStack* SeqStack_Create(int capacity)
{
	return SeqList_Create(capacity);
}

// 销毁栈,相当于销毁链表
void* SeqStack_Destroy(SeqStack* stack)
{
	SeqList_Destroy(stack);

	return NULL;
}

// 清空栈,相当于清空链表
void* SeqStack_Clear(SeqStack* stack)
{
	SeqList_Clear(stack);
	return NULL;
}

// 元素入栈,相当于在线性表(数组)的尾部添加元素
int SeqStack_Push(SeqStack* stack, void* item)
{
	return SeqList_Insert(stack, item, SeqList_Length(stack));
}

// 弹出栈顶元素,相当于从线性表的尾部删除元素
void* SeqStack_Pop(SeqStack* stack)
{
	return SeqList_Delete(stack, SeqList_Length(stack) - 1);
}

// 获取栈顶元素,相当于获取链表的尾部元素
void* SeqStack_Top(SeqStack* stack)
{
	return SeqList_Get(stack, SeqList_Length(stack) - 1);
}

// 获取栈的大小,相当于获取链表的长度
int SeqStack_Size(SeqStack* stack)
{
	return SeqList_Length(stack);
}

// 获取栈的容量
int SeqStack_Capacity(SeqStack* stack)
{
	return SeqList_Capacity(stack);
}
// main.cpp
// 顺序结构栈的测试程序

#include <stdio.h>
#include "seqstack.h"

void play()
{
	int i = 0;
	SeqStack *stack = NULL;

	int a[10];
	for (i = 0; i < 10; ++i) {
		a[i] = i + 1;
	}

	stack = SeqStack_Create(20);

	// 入栈
	for (int i = 0; i < 5; ++i) {
		SeqStack_Push(stack, &a[i]);
	}

	printf("len:%d \n", SeqStack_Size(stack));
	printf("capacity:%d \n", SeqStack_Capacity(stack));

	printf("top:%d \n", *((int *)SeqStack_Top(stack)));

	// 元素出栈
	while (SeqStack_Size(stack)) {
		printf("%d ", *((int *)SeqStack_Pop(stack)));
	}

	SeqStack_Destroy(stack);
	return;
}

int main()
{
	play();

	return 0;
}

工程代码详情:Github

栈的顺序存储 - 设计与实现 - API实现的更多相关文章

  1. 队列顺序存储 - 设计与实现 - API函数

    队列是一种特殊的线性表 队列仅在线性表的两端进行操作 队头(Front):取出数据元素的一端 队尾(Rear):插入数据元素的一端 队列不允许在中间部位进行操作! queue常用操作 销毁队列 清空队 ...

  2. 线性表的顺序存储设计和实现 - API函数实现

    基本概念 设计与实现 插入元素算法 判断线性表是否合法 判断插入位置是否合法 把最后一个元素到插入位置的元素后移一个位置 将新元素插入 线性表长度加1 获取元素操作 判断线性表是否合法 判断位置是否合 ...

  3. 队列链式存储 - 设计与实现 - API函数

    队列相关基础内容参我的博文:队列顺序存储 - 设计与实现 - API函数 队列也是一种特殊的线性表:可以用线性表链式存储来模拟队列的链式存储. 主要代码: // linkqueue.h // 队列链式 ...

  4. SoC嵌入式软件架构设计之六:API设计方法

    在嵌入式系统中,驱动都是以API的方式提供给应用进行调用.这里介绍嵌入式系统的API设计和管理方法. 驱动在系统中会按模块进行分类,比如按键驱动.LCD驱动.文件系统.card驱动.I2C驱动等等:每 ...

  5. 如何构建和设计以确保 API 的安全性

    如何构建和设计以确保 API 的安全性 面对常见的OWASP十大威胁.未经授权的访问.拒绝服务攻击.以及窃取机密数据等类型的攻击,企业需要使用通用的安全框架,来保护其REST API,并保证良好的用户 ...

  6. C语言- 基础数据结构和算法 - 栈的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  7. Atitit.论图片类型 垃圾文件的识别与清理  流程与设计原则 与api概要设计 v2 pbj

    Atitit.论图片类型 垃圾文件的识别与清理  流程与设计原则 与api概要设计 v2 pbj 1. 俩个问题::识别垃圾文件与清理策略1 2. 如何识别垃圾图片1 2.1. 体积过小文件<1 ...

  8. 如何设计优秀的API(转)

    到目前为止,已经负责API接近两年了,这两年中发现现有的API存在的问题越来越多,但很多API一旦发布后就不再能修改了,即时升级和维护是必须的.一旦API发生变化,就可能对相关的调用者带来巨大的代价, ...

  9. OAuth 2和JWT - 如何设计安全的API?

    OAuth 2和JWT - 如何设计安全的API? Moakap译,原文 OAuth 2 VS JSON Web Tokens: How to secure an API 本文会详细描述两种通用的保证 ...

随机推荐

  1. 在Spring Boot框架下使用WebSocket实现消息推送

    Spring Boot的学习持续进行中.前面两篇博客我们介绍了如何使用Spring Boot容器搭建Web项目(使用Spring Boot开发Web项目)以及怎样为我们的Project添加HTTPS的 ...

  2. 搭建ejabberd集群

    搭建ejabberd集群(金庆的专栏 2016.8)以2台机器搭建一个ejabberd集群.2台机器都是外网一块网卡,内网另一块网卡.新建一个域名,添加2台机器的外网IP.分别用源码安装ejabber ...

  3. 自定义progressDialog(数据加载框)的实现

    大家在开发客户端时基本上都需要获取数据,在获取数据时会有一个等待状态,这时我们可以利用系统自带的progressDialog来向用户展示"数据正在加载中..."等等,但有时我们会觉 ...

  4. Nginx - 代理、缓存

    Nginx 标签 : nginx 代理 代理服务可简单的分为正向代理和反向代理: 正向代理: 用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送 ...

  5. EBS多组织结构

    1. 业务组: 它代表组织结构的最高层次, 它分离了人力资源的信息. 例如, 当你查询人员时, 它会列出所有分配给相应业务组的成员, 而你自己所属于的组织只不过是业务组的一份子. 这样说可能造成一种误 ...

  6. Dynamics CRM 自定义上传附件的图片悬浮层显示

    CRM中的附件是以流的形式保存在了数据库中,这样做的一个坏处是一旦系统运行时间久,附件上传的多了势必会导致数据库极速扩大,即影响系统的运行效率也对后期的迁移维护带来了不必要的麻烦.所以很多的客户都会要 ...

  7. windows下安装nginx (转载自:http://blog.163.com/njut_wangjian/blog/static/1657964252013327103716818/)

    1.  到nginx官网上下载相应的安装包,http://nginx.org/en/download.html:下载进行解压,将解压后的文件放到自己心仪的目录下,我的解压文件放在了d盘根目录下,如下图 ...

  8. Android 推送和统计最优轮循(心跳策略)探究实践

    http://blog.csdn.net/sk719887916/article/details/51398416 skay亲笔 Android开发中经常会用到周期性执行一个动作的需求,大的场景有推送 ...

  9. 查全率(召回率)、精度(准确率)和F值

    文献中的recall rate(查全率或召回率) and precision(精度)是很重要的概念.可惜很多中文网站讲的我都稀里糊涂,只好用google查了个英文的,草翻如下:召回率和精度定义: 从一 ...

  10. iOS隐藏键盘的几种方式

    因为开发中经常要用到textField和textView,在某些情形下隐藏键盘很有必要,而隐藏键盘有多种方式,在合适的场景下用合适的方式隐藏就显得很重要,我也老是记不起来有哪些方法,这里就记录一下,以 ...