Table of contents
1) Data is pushed onto the stack
1) Get the top data of the stack
2) Get the number of stack elements
4. Implementation of Sequential Stack
4. Determine whether the stack is empty
5. Determine whether the stack is saturated
8. Get the top element of the stack
9. Release the memory requested by malloc
Example of printing all elements in the stack
5. Linked list implementation of stack
4. Determine whether the stack is empty
7. Get the top element of the stack
8. Release the memory requested by malloc
Example of printing all elements in the stack
6. Advantages and Disadvantages of Two Implementations
1. Sequence table implementation
1. Concept
1. Definition of stack
A stack is a linear list where insertions and deletions are limited to the end of the list . The stack is also called a Last In First Out (Last In First Out) linear list, or LIFO for short.
2. Top of stack
The stack is a linear list, and we call the end that allows insertion and deletion the top of the stack .
3. Bottom of the stack
Opposite to the top of the stack , the other end is called the bottom of the stack . In fact, we don't need to care about the elements at the bottom of the stack.
2. Interface
1. Writable interface
1) Data is pushed onto the stack
The insertion operation of the stack is called pushing , which can also be called pushing or pushing. As shown in the figure below, it represents three push operations:
2) Data popping
The deletion operation of the stack is called stack popping. As shown in the figure below, it represents two pop operations:
3) Clear the stack
Keep popping the stack until the stack is empty, as shown in the following figure:
2. Read-only interface
1) Get the top data of the stack
For a stack, only the top data can be obtained, and other data is generally not supported.
2) Get the number of stack elements
The number of stack elements is generally stored in an extra variable, which is incremented by one when pushed onto the stack and decremented by one when popped out of the stack . In this way, there is no need to traverse the entire stack when obtaining stack elements. Obtain the number of stack elements with a time complexity of �(1)O(1).
3) Stack empty judgment
When the number of stack elements is zero, it is an empty stack. Pop operations are not allowed on an empty stack .
3. Basic operations of stack
Create an empty stack: CreateStack (len)
Clear stack: ClearStack (S)
Determine whether the stack is empty: EmptyStack (S)
Determine whether the stack is full: FullStack (S)
Push elements onto the stack: PushStack (S,x)
Element pop: PopStack (S)
Get the top element of the stack: GetTop (S)
4. Implementation of Sequential Stack
1. Data structure definition
For the sequence table, which is represented as an array in C language , before defining the stack , we need to consider the following points:
1) The storage method of stack data, and the data type of stack data;
2) The size of the stack;
3) stack top pointer;
- We can define a stack structure , and the C language implementation is as follows:
typedef int datatype;
typedef struct node{ /*定义栈中数据元素的数据类型*/
datatype *data; /*用指针指向栈的存储空间*/
int maxlen; /*当前栈的最大元素个数*/
int top; /*指示栈顶位置(数组下标)的变量*/
}sqstack; /*顺序栈类型定义*/
2. Create a stack
The C language implementation is as follows:
sqstack* stack_create(int len)
{
sqstack *s;
if((s=(sqstack *)malloc(sizeof(sqstack)))==NULL)
{
puts("malloc failed");
return NULL;
}
if((s->data=(datatype *)malloc(len*sizeof(datatype)))==NULL)
{
puts("malloc failed");
return NULL;
}
s->maxlen=len;
s->top=-1;
return s;
}
3. Clear the stack
The C language implementation is as follows:
void stack_clear(sqstack* s)
{
s->top = -1;
}
4. Determine whether the stack is empty
The C language implementation is as follows:
int stack_empty(sqstack* s)
{
return (s->top==-1 ? 1:0);
}
5. Determine whether the stack is saturated
The C language implementation is as follows:
int stack_full(sqstack* s)
{
return (s->top==(s->maxlen-1) ? 1:0);
}
6. Push into the stack
The C language implementation is as follows:
int stack_push(sqstack* s,datatype value)
{
if(s->top==s->maxlen-1){
puts("stack is full");
return -1;
}
s->data[s->top+1]=value;
s->top++;
return 1;
}
7. Get out of the stack
The C language implementation is as follows:
datatype stack_pop(sqstack* s)
{
s->top--;
return s->data[s->top+1];
}
8. Get the top element of the stack
The C language implementation is as follows:
datatype stack_top(sqstack* s)
{
return(s->data[s->top]);
}
9. Release the memory requested by malloc
The C language implementation is as follows:
void stack_free(sqstack *s)
{
free(s->data);
s->data=NULL;
free(s);
s=NULL;
}
Example of printing all elements in the stack
The C language implementation is as follows:
sqstack.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node{
datatype *data;
int maxlen;
int top;
}sqstack;
extern sqstack* stack_create(int len);
extern int stack_empty(sqstack* s);
extern int stack_full(sqstack* s);
extern void stack_clear(sqstack* s);
extern int stack_push(sqstack* s,datatype value);
extern datatype stack_pop(sqstack* s);
extern datatype stack_top(sqstack* s);
extern void stack_free(sqstack *s);
#endif
sqstack.c
#include "sqstack.h"
sqstack* stack_create(int len)
{
sqstack *s;
if((s=(sqstack *)malloc(sizeof(sqstack)))==NULL)
{
puts("malloc failed");
return NULL;
}
if((s->data=(datatype *)malloc(len*sizeof(datatype)))==NULL)
{
puts("malloc failed");
return NULL;
}
s->maxlen=len;
s->top=-1;
return s;
}
int stack_empty(sqstack* s)
{
return (s->top==-1 ? 1:0);
}
int stack_full(sqstack* s)
{
return (s->top==(s->maxlen-1) ? 1:0);
}
void stack_clear(sqstack* s)
{
s->top = -1;
}
int stack_push(sqstack* s,datatype value)
{
if(s->top==s->maxlen-1){
puts("stack is full");
return -1;
}
s->data[s->top+1]=value;
s->top++;
return 1;
}
datatype stack_pop(sqstack* s)
{
s->top--;
return s->data[s->top+1];
}
datatype stack_top(sqstack* s)
{
return(s->data[s->top]);
}
void stack_free(sqstack *s)
{
free(s->data);
s->data=NULL;
free(s);
s=NULL;
}
test.c
#include "sqstack.h"
int main(int argc, const char *argv[])
{
sqstack *s;
int n=5;
s=stack_create(n);
stack_push(s,10);
stack_push(s,20);
stack_push(s,30);
stack_push(s,40);
stack_push(s,50);
stack_push(s,60);
while(!stack_empty(s))
{
printf("%d ",stack_pop(s));
}
putchar(10);
stack_clear(s);
stack_free(s);
return 0;
}
Makefile
CC = gcc
CFLAGS = -g -Wall
test:test.o sqstack.o
$(CC) $(CFLAGS) -o $@ $^
.PHONY:clean
clean:
rm test *.o
-g: Generates the necessary symbol information for the symbolic debugging tool (GNU's gdb). If we want to debug the source code, we must add this option.
-Wall: Indicates that all useful alarm information of gcc is allowed to be issued
-c: Just compile without linking, and generate the target file ".o "
-o test: means outputting the output file to file
operation result:
5. Linked list implementation of stack
1. Data structure definition
For linked lists, before defining the stack , we need to consider the following points:
1) The storage method of stack data and the data type of stack data;
2) The size of the stack;
3) The top pointer of the stack;
We can define a stack structure , and the C language implementation is as follows:
typedef int datatype;
typedef struct node{
datatype data;
struct node* next;
}listnode,*linklist;
2. Create a stack
The C language implementation is as follows:
linklist stack_create()
{
linklist s;
if((s=(linklist)malloc(sizeof(listnode)))==NULL){
puts("malloc failed");
return NULL;
}
s->next=NULL;
return s;
}
3. Clear the stack
The C language implementation is as follows:
void stack_clear(linklist s)
{
linklist p;
printf("clear:");
p=s->next;
while(p)
{
s->next=p->next;
printf("%d ",p->data);
free(p);
p=s->next;
}
putchar(10);
}
4. Determine whether the stack is empty
The C language implementation is as follows:
int stack_empty(linklist s)
{
return (s->next==NULL ? 1:0);
}
5. Push into the stack
The C language implementation is as follows:
int stack_push(linklist s,datatype value)
{
linklist p;
if((p=(linklist)malloc(sizeof(listnode)))==NULL)
{
puts("malloc failed");
return -1;
}
p->data = value;
p->next=s->next;
s->next = p;
return 0;
}
6. Pop out
The C language implementation is as follows:
datatype stack_pop(linklist s)
{
linklist p;
datatype ret;
p=s->next;
s->next=p->next;
ret=p->data;
free(p);
p=NULL;
return ret;
}
7. Get the top element of the stack
The C language implementation is as follows:
datatype stack_top(linklist s)
{
return (s->next->data);
}
8. Release the memory requested by malloc
The C language implementation is as follows:
void stack_free(linklist s)
{
linklist p;
printf("free:");
p=s;
while(p)
{
s=s->next;
printf("%d ",p->data);
free(p);
p=s;
}
putchar(10);
}
Example of printing all elements in the stack
The C language implementation is as follows:
linkstack.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node{
datatype data;
struct node* next;
}listnode,*linklist;
extern linklist stack_create();
extern int stack_empty(linklist s);
extern void stack_clear(linklist s);
extern int stack_push(linklist s,datatype value);
extern datatype stack_pop(linklist s);
extern datatype stack_top(linklist s);
extern void stack_free(linklist s);
#endif
linkstack.c
#include "linkstack.h"
linklist stack_create()
{
linklist s;
if((s=(linklist)malloc(sizeof(listnode)))==NULL){
puts("malloc failed");
return NULL;
}
s->next=NULL;
return s;
}
int stack_empty(linklist s)
{
return (s->next==NULL ? 1:0);
}
int stack_push(linklist s,datatype value)
{
linklist p;
if((p=(linklist)malloc(sizeof(listnode)))==NULL)
{
puts("malloc failed");
return -1;
}
p->data = value;
p->next=s->next;
s->next = p;
return 0;
}
datatype stack_pop(linklist s)
{
linklist p;
datatype ret;
p=s->next;
s->next=p->next;
ret=p->data;
free(p);
p=NULL;
return ret;
}
datatype stack_top(linklist s)
{
return (s->next->data);
}
void stack_clear(linklist s)
{
linklist p;
printf("clear:");
p=s->next;
while(p)
{
s->next=p->next;
printf("%d ",p->data);
free(p);
p=s->next;
}
putchar(10);
}
void stack_free(linklist s)
{
linklist p;
printf("free:");
p=s;
while(p)
{
s=s->next;
printf("%d ",p->data);
free(p);
p=s;
}
putchar(10);
}
test.c
#include "linkstack.h"
int main(int argc, const char *argv[])
{
linklist s;
s=stack_create();
stack_push(s,10);
stack_push(s,20);
stack_push(s,30);
stack_push(s,40);
stack_push(s,50);
stack_push(s,60);
#if 0
while(!stack_empty(s))
{
printf("%d ",stack_pop(s));
}
putchar(10);
#endif
// stack_clear(s);
stack_free(s);
return 0;
}
Makefile
CC = gcc
CFLAGS = -g -Wall
test:test.o linkstack.o
$(CC) $(CFLAGS) -o $@ $^
.PHONY:clean
clean:
rm test *.o
operation result:
6. Advantages and Disadvantages of Two Implementations
1. Sequence table implementation
When using a sequence table to implement a stack, the constant time complexity of pushing and popping the stack is low, and the stack clearing operation can be O(1) compared to the linked list implementation . The only shortcoming is that it needs to apply for space in advance, and When the space is not enough, expansion is required. The expansion method is not mentioned in this article. You can refer to the article: "100 C/C++ Interview Examples" (4) Vector expansion strategy .
2. Linked list implementation
When using a linked list to implement a stack, the constant time complexity of pushing and popping the stack is slightly higher. The main reason is that every time a stack element is inserted, space needs to be applied for, and every time a stack element is deleted, space needs to be released, and the stack clearing operation is O(n ), directly setting the top pointer of the stack to empty will cause a memory leak. The advantage is: there is no need to pre-allocate space, and within the allowed memory range, it can be pushed onto the stack without any restrictions on the sequence table.