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. Kafka系列之-自定义Producer

    前面已经讲到了,在Kafka中,Message是由Producer产生的,Producer产生的Message会发送到Topic的指定Partition中.Producer可以有多种形式,也可以由用户 ...

  2. 解决 oracle IO占用率很高的问题

    突然user io占用率很很高,看了一个AWR报告,发现direct path read temp,direct path write temp的的数率很高,后来怀疑是临时表空间不够了,就试着设了一下 ...

  3. Android新特性Instant Run详解

    关于 Instant Run Android Studio 2.0 中引入的 Instant Run 是 Run 和 Debug 命令的行为,可以大幅缩短应用更新的时间.尽管首次构建可能需要花费较长的 ...

  4. BI Publisher(rtf)模板开发语法大全

    Rtf模板开发例如背景,纹理分栏等等功能都能用word工具实现不再具体总结大家可以参考word教程.....   一.组 定义一个组的目的是告诉XMLPublisher对重复的数据行进行循环显示,也就 ...

  5. Linux 环境下的一些常用命令(三)

    转载自 http://www.oschina.net/translate/20-advanced-commands-for-middle-level-linux-users 21. 命令: Find ...

  6. C语言诠释--为什么内存是线性分布的。

    Author:伟易达集团软件工程师 II 杨源鑫Date :2016.11.11Subject:内存为什么是线性分布的 今天有位小伙伴问了我一个问题,问题大概是这样描述的:      师兄,我如何能够 ...

  7. 使用DWR实现自动补全 类似百度搜索框的自动显示效果

    使用DWR实现自动补全 自动补全:是指用户在文本框中输入前几个字母或汉字的时候,自动在存放数据的文件或数据库中将所有以这些字母或汉字开头的数据提示给用户供用户选择 在日常上网过程中,我们经常使用搜索引 ...

  8. 19 Handler 总结

    Handler 一, 回顾异步任务 AsyncTask 二, android 使用线程的规则 1,在主线程 不能做阻塞操作 2,在主线程之外的线程不能更新Ui 三, Handler的作用 1,在子线程 ...

  9. ORACLE数据库学习之SQL性能优化详解

                                                                                    Oracle  sql 性能优化调整 ...

  10. 【NPR】漫谈轮廓线的渲染

    写在前面 好久没写文章.最近在看<Real Time Rendering, third edition>这本书,看到了NPR这一章就想顺便记录下一些常见的轮廓线渲染的方法. 在非真实感渲染 ...