【数据结构和算法】了解认识栈,并实现栈的相关函数
创始人
2024-05-20 07:37:40

到现在我们了解并认识了线性表的概念,动态、静态顺序表的建立,以及两种链表的实现,接下来我们要认识一个新的内容,新的概念,栈,是基于顺序表或者链表的一种新型数据结构。

目录

一、栈是什么?

二、栈的实现

1.实现的方式

2.实现栈的函数

1.初始化栈

2.入栈

3.出栈

4.查看栈顶元素

5.打印栈和清空栈

三、完整代码实现

1.链表实现栈

2.数组(顺序表)实现栈

总结


一、栈是什么?

栈:是一种特殊的线性表。其只允许在固定的一端进行插入和删除操作。进行数据的插入和删除的一端称为栈顶,另外的一端称为栈底。栈中的数据元素遵循先进后出(后进先出)的原则

之前在学习C语言的时候,就i听说过的两种概念

1.压栈:栈的插入操作叫做进栈、压栈、入栈等,插入数据在栈顶

2.出栈:栈的删除操作叫做出栈。出数据也在栈顶

 

二、栈的实现

1.实现的方式

有两种

1.我们可以通过顺序表的形式实现,因为进行尾插尾删除,代价小,就算是更改或者删除栈中指定的元素,不过也是移动位置而已。


如图所示:

结构体代码如下:

#define MAX 100
#define CAp 4 ///初始化的时候capacity的容量
#define Make 2//每一次增加的newCapacity的容量
//静态
typedef struct Stacknode {int data[MAX];//数据域int size;//表示元素个数
}Stack;
//动态
typedef struct Stacknode2 {int* data;//数据域int size;//表示元素个数int capacity;//表示当前容量
}Stack1;

2.通过链表的形式进行实现栈表

结构体如下:

//创建基础结构
typedef struct node {int data;struct node* next;
}ST;//栈实际上就是一个只能进行头插头删的单向链表
//创建栈的头尾结点 结构体
typedef struct stack {struct node* top;//栈顶元素地址struct node* bottom;//栈底元素地址int size;//栈的元素个数
};

2.实现栈的函数

以链表实现栈为例,在本文结尾处,一并放置用数组实现栈的完整代码

1.初始化栈

结构体如上,使用的是上文的结构体类型

代码如下:


//初始化栈
struct stack* create_stack()
{struct stack* s = (struct stack*)malloc(sizeof(struct stack));s->size = 0;s->bottom = s->top = NULL;return s;
}

使用malloc函数,申请空间,将s的size大小置为0,bottom和top表示栈底栈顶都指向NULL

2.入栈

如图所示:

 代码如下:

//创建新的结点
struct node* create_node(int data) {struct node* newnode = (struct node*)malloc(sizeof(struct node));newnode->next = NULL;newnode->data = data;return newnode;
}//入栈
//入栈首先要将准备入栈的元素封装成结点,和链表没有差别void stackPush(struct stack* s, int x) {ST* newnode = create_node(x);newnode->next = s->top;s->top = newnode;s->size++;
}

3.出栈

如图所示:

代码如下:

//出栈
void stackPop(struct stack* s, int* x) {
//判断是否为空栈   如果是 空栈的话就  使得输出 Pop failedif (s->size == 0) {printf("Pop failed\n");exit(-1);}//创建结点临时变量  赋值得到栈顶元素ST* tmp = s->top;*x = tmp->data;//得到数值s->top = tmp->next;s->size--;
}

4.查看栈顶元素

代码如下:

//查看栈顶元素
void stackTop(struct stack* s, int* x) {if (s->size == 0) {printf("空栈~~\n");exit(-1);}*x = s->top->next->data;
}

5.打印栈和清空栈

代码如下:

//清空栈
void make_stack_empty(struct stack* s) {s->size = 0;s->bottom = s->top ;//将栈底等于栈顶就可以  然后将size为0}
void stackPrint(struct stack* s) {//打印栈表ST* list = s->top;printf("top -> ");while (list!=NULL) {printf("%d -> ", list->data);list = list->next;}
}

三、完整代码实现

1.链表实现栈

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include//创建基础结构
typedef struct node {int data;struct node* next;
}ST;//栈实际上就是一个只能进行头插头删的单向链表
//创建栈的头尾结点 结构体
typedef struct stack {struct node* top;//栈顶元素地址struct node* bottom;//栈底元素地址int size;//栈的元素个数
};
//表示每一个栈都是struct stack* 类型的,栈中的每一个怨怒是都是struct node *类型的  不仅需要为栈分配内存,还需要为压入栈中的元素分配内存/*
node中的next指针用于让栈中上面的节点连接到下面的节点,stack中的top和bottom分别存放当前栈顶元素的地址和栈底元素的后一个位置的地址(NULL),
因为是用于指向栈中节点的指针,所以得是struct node* 类型。*///初始化栈
struct stack* create_stack()
{struct stack* s = (struct stack*)malloc(sizeof(struct stack));s->size = 0;s->bottom = s->top = NULL;return s;
}//一开始栈是空的所以 size为0  top  bottom是NULL//创建新的结点
struct node* create_node(int data) {struct node* newnode = (struct node*)malloc(sizeof(struct node));newnode->next = NULL;newnode->data = data;return newnode;
}//入栈
//入栈首先要将准备入栈的元素封装成结点,和链表没有差别void stackPush(struct stack* s, int x) {ST* newnode = create_node(x);newnode->next = s->top;s->top = newnode;s->size++;
}//出栈
void stackPop(struct stack* s, int* x) {
//判断是否为空栈   如果是 空栈的话就  使得输出 Pop failedif (s->size == 0) {printf("Pop failed\n");exit(-1);}//创建结点临时变量  赋值得到栈顶元素ST* tmp = s->top;*x = tmp->data;//得到数值s->top = tmp->next;s->size--;
}//查看栈顶元素
void stackTop(struct stack* s, int* x) {if (s->size == 0) {printf("空栈~~\n");exit(-1);}*x = s->top->next->data;
}//清空栈
void make_stack_empty(struct stack* s) {s->size = 0;s->bottom = s->top ;//将栈底等于栈顶就可以  然后将size为0}
void stackPrint(struct stack* s) {//打印栈表ST* list = s->top;printf("top -> ");while (list!=NULL) {printf("%d -> ", list->data);list = list->next;}
}
int main()
{struct stack *s = create_stack();stackPush(s, 1);stackPush(s, 2);stackPush(s, 3);stackPush(s, 4);stackPush(s, 5);stackPrint(s);int a = 0;stackPop(s,&a);printf("\n%d\n", a);stackPrint(s);return 0;
}

2.数组(顺序表)实现栈

#define _CRT_SECURE_NO_WARNINGS
#include"steck.h"
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
//栈是限定在一个表里面的一段进行插入删除操作的线性表
// 数据进出的顺序为先进后处
// 应用场景:网页浏览的时候的后退  编辑软件的撤销
// 
//创建栈  两个方式:数组(顺序表)和 单链表//1.数组:选用数组用来做栈的存储结构,只需要在数组末尾进行操作即可,完美避开数组操作中挪动数据缺陷//   显然是可以用数组来做栈的存储结构
//2.单链表  :因为栈是吸纳星表的一段进行操作,所以一般是用链表头进行操作//进行头插头删  是用链表更好 效率更高//1.用数组的方式
typedef int StackDataType;
typedef struct Stcak {StackDataType* data;int top;int capacity;   //数据域和元素个数
}ST;//初始化
void StackInit(ST* ps) {ps->data = (StackDataType*)malloc(sizeof(StackDataType) * 4);if (ps->data == NULL) {printf("malloc failed\n");exit(-1);}ps->top = 0;ps->capacity = 4;}
//压栈
void StackPush(ST* ps, int x) {assert(ps);//断言//满了就扩容if (ps->top == ps->capacity) {StackDataType* tmp = (StackDataType*)realloc(ps->data, sizeof(StackDataType) * ps->capacity * 2);if (tmp == NULL) {printf("realloc failed\n");exit(-1);}else {ps->data = tmp;ps->capacity *= 2;}}ps->data[ps->top] = x;ps->top++;}
//出栈
void StackPop(ST* ps) {//出栈是将最后一个元素放出来  先进后出assert(ps);assert(ps->top > 0);//断言进行判断是否栈为空  即top!=0ps->top--;//直接减减就可以  没有了对应元素 的数据  如果再次压栈的话 会把之前的数据进行更改
}//取得栈顶元素
StackDataType StackTop(ST* ps) {assert(ps);assert(ps->top > 0);return ps->data[ps->top - 1];//因为top栈顶始终要保持比元素个数大一,保证压栈的时候先压栈然后再加加
//所以取栈顶元素 的时候 top-1
}//销毁栈
void StackDestory(ST* ps) {assert(ps);free(ps->data);//释放数组data的空间ps->data = NULL;ps->top = ps->capacity = 0;}//求栈中元素个数
int StackSize(ST* ps) {assert(ps);return ps->top;
}
//判断是否为空
bool StackEmpty(ST* ps) {assert(ps);return ps->top == 0;
}
void StackPrint(ST* ps) {//打印栈表assert(ps);for (int i = 0; i < ps->top; i++) {printf("%d ", ps->data[i]);}printf("\n");
}
int main()
{ST s;ST *ps=&s;/*  StackInit(&ps);StackPush(&ps, 1);StackPush(&ps, 2);StackPush(&ps, 3);StackPush(&ps, 4);StackPush(&ps, 5);StackPrint(&ps);*/StackInit(ps);StackPush(ps, 1);StackPush(ps, 2);StackPush(ps, 3);StackPush(ps, 4);StackPush(ps, 5);StackPop(ps);//出栈成功StackPrint(ps);printf("%d \n", StackTop(ps));//取得栈顶元素printf("%d \n", StackSize(ps));//获得栈表元素个数StackDestory(ps);StackPrint(ps);//销毁栈表成功return 0;
}

总结

栈是限定在一个表里面的一段,对其进行插入删除操作的线性表,数据进出的顺序为先进后处,应用场景:网页浏览的时候的后退  编辑软件的撤销,实际上栈的功能就这样,学会顺序表以及链表的使用,对于栈来讲,只是懂得头擦头删,理解概念了,就好掌握并实现栈。

下文,我们会讲解一下队列,和栈相似,但是另有不同,敬请期待吧,感谢大家支持!!!

相关内容

热门资讯

世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...