栈的实现与操作(C语言实现)

栈的定义

 1, 栈是一种特殊的线性表

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

 3,栈顶(Top): 同意操作的一端 同意操作的一端

 4,栈底(Bottom): ,不同意操作的一端 不同意操作的一端

这里我做出了 栈的顺序实现 和 链式实现。分别例如以下:

=========================================华丽丽的切割线==========================================================

栈的顺序实现:

首先,我们要弄明确的是。栈本质上就是线性表。是一种特殊的线性表。仅仅是仅仅能在一端进行操作罢了。故而非常多操作线性表是非常类似的。因此,我们能够将之前写的  顺序线性表的实现及操作(C语言实现) 中的代码直接拿过来使用,以达到代码复用的效果(代码就不在此处追述了)。

头文件:

#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

源文件:

// 栈.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <malloc.h>
#include <stdlib.h>
#include "SeqStack.h"
#include "SeqList.h"

int _tmain(int argc, _TCHAR* argv[])
{
	 SeqStack* stack = SeqStack_Create(20);
    int a[10];
    int i = 0;

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

        SeqStack_Push(stack, a + i);
    }

    printf("Top: %d\n", *(int*)SeqStack_Top(stack));
    printf("Capacity: %d\n", SeqStack_Capacity(stack));
    printf("Length: %d\n", SeqStack_Size(stack));

    while( SeqStack_Size(stack) > 0 )
    {
        printf("Pop: %d\n", *(int*)SeqStack_Pop(stack));
    }

    SeqStack_Destroy(stack);
	system("pause");
	return 0;
}
//创建栈
SeqStack* SeqStack_Create(int capacity)
{
    return SeqList_Create(capacity);
}
//销毁
void SeqStack_Destroy(SeqStack* stack)
{
    SeqList_Destroy(stack);
}
//清空
void SeqStack_Clear(SeqStack* stack)
{
    SeqList_Clear(stack);
}
//压栈
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);
}

执行结果:

Top: 9
Capacity: 20
Length: 10
Pop: 9
Pop: 8
Pop: 7
Pop: 6
Pop: 5
Pop: 4
Pop: 3
Pop: 2
Pop: 1
Pop: 0
请按随意键继续. . .

=====================================我是切割线========================================================

栈的链式实现:

     同栈的顺序实现一样,栈的链式实现本质上事实上就是单链表的形式,也仅仅是在一头操作罢了,因此我们这里亦採用代码复用的方法,详细代码请參阅:链表的实现与操作(C语言实现) 。

头文件:

#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_

typedef void LinkStack;

LinkStack* LinkStack_Create();

void LinkStack_Destroy(LinkStack* stack);

void LinkStack_Clear(LinkStack* stack);

int LinkStack_Push(LinkStack* stack, void* item);

void* LinkStack_Pop(LinkStack* stack);

void* LinkStack_Top(LinkStack* stack);

int LinkStack_Size(LinkStack* stack);

#endif

源文件:

#include "stdafx.h"
#include "LinkList.h"
#include "LinkStack.h"
#include <malloc.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    LinkStack* stack = LinkStack_Create();
    int a[10];
    int i = 0;

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

        LinkStack_Push(stack, a + i);
    }

    printf("Top: %d\n", *(int*)LinkStack_Top(stack));
    printf("Length: %d\n", LinkStack_Size(stack));

    while( LinkStack_Size(stack) > 0 )
    {
        printf("Pop: %d\n", *(int*)LinkStack_Pop(stack));
    }

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

typedef struct _tag_LinkStackNode
{
    LinkListNode header;
    void* item;
} TLinkStackNode;
//创建
LinkStack* LinkStack_Create()
{
    return LinkList_Create();
}

//销毁
void LinkStack_Destroy(LinkStack* stack)
{
    LinkStack_Clear(stack);
    LinkList_Destroy(stack);
}

//清空
void LinkStack_Clear(LinkStack* stack)
{
    while( LinkStack_Size(stack) > 0 )
    {
        LinkStack_Pop(stack);
    }
}

//压栈
int LinkStack_Push(LinkStack* stack, void* item)
{
    TLinkStackNode* node = (TLinkStackNode*)malloc(sizeof(TLinkStackNode));
    int ret = (node != NULL) && (item != NULL);

    if( ret )
    {
        node->item = item;

        ret  = LinkList_Insert(stack, (LinkListNode*)node, 0);
    }

    if( !ret )
    {
        free(node);
    }

    return ret;
}

//出栈
void* LinkStack_Pop(LinkStack* stack)
{
    TLinkStackNode* node = (TLinkStackNode*)LinkList_Delete(stack, 0);
    void* ret = NULL;

    if( node != NULL )
    {
        ret = node->item;

        free(node);
    }

    return ret;
}

//获得栈顶
void* LinkStack_Top(LinkStack* stack)
{
    TLinkStackNode* node = (TLinkStackNode*)LinkList_Get(stack, 0);
    void* ret = NULL;

    if( node != NULL )
    {
        ret = node->item;
    }

    return ret;
}

//获得栈的大小
int LinkStack_Size(LinkStack* stack)
{
    return LinkList_Length(stack);
}

执行结果:

Top: 9
Length: 10
Pop: 9
Pop: 8
Pop: 7
Pop: 6
Pop: 5
Pop: 4
Pop: 3
Pop: 2
Pop: 1
Pop: 0
请按随意键继续. . .

如有错误,望不吝指出~

时间: 2024-10-06 20:35:25

栈的实现与操作(C语言实现)的相关文章

只使用递归实现栈的逆序操作

2017-06-23 20:36:02 刚开始思考这个问题的时候陷入了一个误区,就是以为只能用一个递归完成. 然而事实上,可以使用两个递归来完成这个功能. 具体思考是这样的,首先递归其实是将问题规模缩小了,每次处理更小的问题.针对这题来说,更小的问题应该是去除底部那个数后的逆序再加上最后的数. 当然,你可能会问,什么不是去掉最上面的数,然后将它再放到最前面,理由很简单,栈是一种后进先出的数据结构,这种类型的数据结构适合的是在尾部添加数据,而非在首部添加数据,所以更清晰的或者说更适合栈的操作是先把

树的实现与操作(C语言实现)

首先来简单说下一些关于的基本概念. 树是一种非线性的数据结构 1,树是由 n(n>=0)个结点组成的有限集合 如果n = 0 ,称为空树 如果n > 0,则: 有一个特定的称之为根(root)的结点,它只有直接后继,但没有直接前驱 除了根以外的其他结点划分为:m(m>=0)个互不相交的有限集合,T0,T1,T2-Tn-1,每个集合又是一棵树,并且称之为根的子树 2,树中的概念: 树的结点包括一个数据及若干指向子树的分支 结点拥有的子树树称为结点的度 度为0的结点称为叶结点 度不为0的结点

静态链表的实现与操作(C语言实现)

我们知道要实现单链表,必须要有指针,那么像Java这样没有指针的的语言就略显蛋疼了. 没关系,我们有静态链表,其本质就是用采用数组的方式实现单链表的功能. 头文件: #ifndef _StaticLinkList_H_ #define _StaticLinkList_H_ typedef void StaticLinkList; typedef void StaticLinkListNode; StaticLinkList * StaticLinkList_Create(int capacity

给定一个二进制数,要求循环移位,在原二进制数中操作(C语言)

int b = 0, c = 0;// b 输入的0~255之间的数 c 移动位数 printf("请输入一个整数和移动位数\n"); scanf("%d%d", &b, &c); unsigned char a = b; unsigned char left = 0;//存储左移之后的结果     unsigned char right = 0;//存储右移之后的结果     //循环移位 right = a >> c; left =

双向链表的实现与操作(C语言实现)

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.一般我们都构造双向循环链表. 单链表的局限 1,单链表的结点都只有一个指向下一个结点的指针 2,单链表的数据元素无法直接访问其前驱元素 3,逆序访问单链表中的元素是极其耗时的操作 双向链表的操作 双向链表的新操作 1,获取当前游标指向的数据元素 2,将游标重置指向链表中的第一个数据元素 3,将游标移动指向到链表中的下一个数据

neo4j初次使用学习简单操作-cypher语言使用

Neo4j 使用cypher语言进行操作 Cypher语言是在学习Neo4j时用到数据库操作语言(DML),涵盖对图数据的增删改查  neo4j数据库简单除暴理解的概念: Neo4j中不存在表的概念,只有两类:节点(Node)和关联(Relation),可以简单理解为图里面的点和边.在数据查询中,节点一般用小括号(),关联用中括号[].当然也隐含路径的概念,是用节点和关联表示的,如:(a)-[r]->(b),表示一条从节点a经关联r到节点b的路径.  备份Neo4j的数据: 1)停掉数据库. 2

循环链表的实现与操作(C语言实现)

循环链表是另一种形式的链式存贮结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环. 循环链表的操作 1,循环链表的新操作 2, 获取当前游标指向的数据元素 3, 将游标重置指向链表中的第一个数据元素 4,将游标移动指向到链表中的下一个数据元素 5,直接指定删除链表中的某个数据元素 CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node); CircleListNode*

二叉树的实现与操作(C语言实现)

 二叉树的定义:     上一篇的树的通用表示法太过于复杂,由此这里采用了孩子兄弟表示法来构建二叉树. 孩子兄弟表示法: 每个结点包含一个数据指针和两个结点指针 --->数据指针:指向保存于树中的数据 --->孩子结点指针:指向第一个孩子 --->兄弟结点指针:指向第一个右兄弟 二叉树是由 n( n>=0 ) 个结点组成的有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树的.互不相交的二叉树组成. 特殊的二叉树: 定义1:满二叉树(Full Binary T

用有限个栈模拟常数效率操作的队列

问题来源 写这篇博客来源于一次面试的经历.不过并不是我被面试,而是我面试别人.如何用两个栈实现一个队列?这算是一个经典的面试题.因为它经常被拿来用.如果对栈和队列比较掌握的人,就可以轻松的答出来. 然而,那天坐在对面的面试者直接抛出:如何用有限个栈模拟常数效率操作的队列呢?作为一个面试官,我佯装镇定,因为这个和用栈实现队列可是一个天上一个地下的区别.听他说完.之后几个小时的面试,我根本无心面试,脑子里一直在想:他刚才说了啥?到底是怎么操作的?太优秀了! 看完这篇文章,以后面试别人或者被面试的过程