顺序栈和链栈(C语言)

简述

栈(Stack):是限制在表的一端进行插入和删除操作的线性表。又称为后进先出LIFO(Last In First Out)或先进后出FILO(First In Last Out)线性表。

栈顶(Top):允许进行插入、删除操作的一端,又称为表尾。用栈顶指针(top)来指示栈顶元素。

栈底(Bottom):是固定端,又称为表头。

空栈:当表中没有元素时称为空栈。

一般将插入和删除操作称为入栈和出栈。

顺序栈和链栈

栈是一种线性表,所以栈也有线性表的两种存储结构(顺序存储结构和链式存储结构)。

栈的顺序存储结构称为顺序栈,链式存储结构称为链栈。

顺序栈

利用一组地址连续的存储单元依次存放栈底到栈顶的数据元素,栈底位置固定不变,栈顶位置随着入栈和出栈操作而变化。

链栈

链栈是一种特殊的线性链表,和所有链表一样,是动态存储结构,无需预先分配存储空间。

顺序栈

栈的定义

typedef struct stack
{   //存放栈中元素的一维数组
​    STACK_DATA_TYPE data[STACK_SIZE];
​    int top;   //存放栈顶元素的下标
}SeqStack;

初始化栈

S->top = -1;

栈顶元素下标 top 等于 -1 为空栈,所以只需将 top 赋值 -1 即可完成顺序栈的初始化。

是否为空栈

if(S->top == -1)
	return TRUE; 

如果栈顶元素下标 top 等于 -1,则栈是空栈。

是否已满栈

if(S->top == STACK_SIZE-1)
​    return TRUE;

如果栈顶元素下标 top 等于栈的大小(STACK_SIZE - 1),则栈已满。

入栈

S->top++;
S->data[S->top] = val;

先判断是否已经满栈,然后移动栈顶元素下标,再将数据放入栈中。

出栈

*val = S->data[S->top];
S->top--;

先判断栈是否为空,然后将栈顶元素下标对应的数据取出来,移动栈顶元素下标。

获取栈顶

*val = S->data[S->top];

跟出栈的逻辑一样,只是没有移动栈顶元素的下标。

栈的顺序存储结构简称为顺序栈,和线性表类似,用一维数组来存储栈。根据数组是否可以根据需要增大,由可以分为静态顺序栈和动态顺序栈。

静态顺序栈实现如下:

实例1

#include 
#include 

#define TRUE 1
#define FALSE 0
#define STACK_SIZE 8
#define STACK_DATA_TYPE int

typedef struct stack
{   //存放栈中元素的一维数组
​    STACK_DATA_TYPE data[STACK_SIZE];
​    int top;   //存放栈顶元素的下标
}SeqStack;

void InitStack(SeqStack *S)
{        
​    S->top = -1;
}

int IsEmpty(SeqStack *S)
{
​    if(S->top == -1)
​    {
​       printf("栈为空\n");
​       return TRUE; 
​    }
​    else 
​       return FALSE;
}

int IsFull(SeqStack *S)
{
​    if(S->top == STACK_SIZE-1)
​    {
​       printf("栈已满\n");
​       return TRUE;
​    }
​    else
​       return FALSE;
}

int Push_Stack(SeqStack *S, STACK_DATA_TYPE val)
{
​    if(IsFull(S) == TRUE)
​       return FALSE;
​    S->top++;
​    S->data[S->top] = val;
​    return TRUE;
}

int Pop_Stack(SeqStack *S, STACK_DATA_TYPE *val)
{
​    if(IsEmpty(S))
​       return FALSE;
​    *val = S->data[S->top];
​    S->top--;
​    return TRUE;
}

int GetTop(SeqStack *S, STACK_DATA_TYPE *val)
{
​    if(IsEmpty(S))
​       return FALSE;
​    *val = S->data[S->top];
​    return TRUE;
}

void Print_Stack(SeqStack *S)
{
​    int i=0;
​    int size=0;
​    if(S->top == -1)
​    {
​       for(i=0; itop; i++)
​       {
​           printf("|_ _ _ _|\n");   //先打印栈上面为空的部分
​       }
​       size = S->top;
​       while(S->top != -1)      //打印有数据的部分
​       {
​           printf("|__ %d __|\n", S->data[S->top]);
​           S->top--;
​       }
​       S->top = size;
​    }
}

int main()
{
​    SeqStack S;   //不用使用malloc分配内存,因为栈结构体采用数组构建
​    InitStack(&S);   //地址传递,保证每次对栈操作后,栈更新
​    IsEmpty(&S);
​    int val=0;
​    int i=0;
​    for(i=0; i<6; i++)
​    {
​       Push_Stack(&S, i+1);
​    }

​    IsEmpty(&S);
​    Print_Stack(&S);
​    for(i=0; i<2; i++)
​    {
​       Pop_Stack(&S, &val); //地址传递
​       printf("%d ", val);
​    }
​    printf("\n");
​    Print_Stack(&S);
​    GetTop(&S, &val);
​    printf("栈顶元素是:%d\n", val);

​    return 0;
}

输出:

@server:~/test/log/list/stack/array$ gcc -o stack stack.c -g

@server:~/test/log/list/stack/array$ ./stack

栈为空
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|__ 6 __|
|__ 5 __|
|__ 4 __|
|__ 3 __|
|__ 2 __|
|__ 1 __|
6 5
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|__ 4 __|
|__ 3 __|
|__ 2 __|
|__ 1 __|
栈顶元素是:4

实例2:

#include
#define MAXSIZE 50
#define ElemType int

typedef struct {
​    ElemType data[MAXSIZE];
​    int top;
}sqStack;

void InitStack(sqStack &S){
​    S.top = -1; 
}

bool IsEmpty(sqStack &S){
​    if(S.top == -1){
​       return true;
​    }else{
​       return false;
​    }
} 

bool Push_Stack(sqStack &S,ElemType x){
​    if(S.top == MAXSIZE - 1){
​       return false;
​    }
​    S.data[++ S.top] = x;
​    return true;
} 

bool Pop(sqStack &S, ElemType &x){   //使用引用&
​    if(S.top == -1){
​       return false;
​    }
​    x = S.data[S.top --];
​    return true;
}

bool GetTop(sqStack &S,ElemType &x){
​    if(S.top == -1){
​       return false;
​    }
​    x = S.data[S.top];
​    return true;
} 

int main()
{
​    sqStack S;
​    InitStack(S);
​    printf("此时栈顶指针是:%d\n",S.top); 

​    Push_Stack(S,1);     
​    Push_Stack(S,2);

​    int x; 
​    GetTop(S,x);
​    printf("获取栈顶元素:%d\n",x); 

​    Pop(S,x);       //实现部分使用引用&
​    printf("弹出栈顶元素:%d\n",x);
​    Pop(S,x);
​    printf("弹出栈顶元素:%d\n",x);

​    if(IsEmpty(S)){
​       printf("当前为空栈\n");
​    }else {
​       printf("当前栈不为空\n");
​    }
​    return 0;
}

输出:

@server:~/test/log/list/stack/array$ g++ -o gstack gstack.cpp -g

@server:~/test/log/list/stack/array$ ./gstack

此时栈顶指针是:-1
获取栈顶元素:2
弹出栈顶元素:2
弹出栈顶元素:1
当前为空栈

动态顺序栈实现如下:

实例3

#include 
#include 

#define TRUE 1
#define FALSE 0
#define STACK_SIZE 5
#define STACK_DATA_TYPE int

typedef struct stack
{   //存放栈中元素的一维数组
​    STACK_DATA_TYPE data[STACK_SIZE];
​    int top;   //存放栈顶元素的下标
}SeqStack, *PSeqStack;

SeqStack* InitStack(void)
{        
​    SeqStack *S = (SeqStack*)malloc(sizeof(SeqStack));
​    if(NULL != S)
​    {
​       S->top = -1;
​       return S;
​    }
​    else
​    {
​       printf("Memory allocate fail!\n");
​       exit(0);
​    }
}

void Destroy_Stack(PSeqStack *S)
{
​    PSeqStack PS = *S;
​    if(NULL != PS)
​    {
​       free(PS);
​       PS = NULL;
​    }
​    *S = NULL;
​    return;
}

int IsEmpty(SeqStack *S)
{
​    if(S->top == -1)
​    {
​       printf("栈为空\n");
​       return TRUE; 
​    }
​    else 
​       return FALSE;
}

int IsFull(SeqStack *S)
{
​    if(S->top == STACK_SIZE-1)
​    {
​       printf("栈已满\n");
​       return TRUE;
​    }
​    else
​       return FALSE;
}

int Push_Stack(SeqStack *S, STACK_DATA_TYPE val)
{
​    if(IsFull(S) == TRUE)
​       return FALSE;
​    S->top++;
​    S->data[S->top] = val;
​    return TRUE;
}

int Pop_Stack(SeqStack *S, STACK_DATA_TYPE *val)
{
​    if(IsEmpty(S))
​       return FALSE;
​    *val = S->data[S->top];
​    S->top--;
​    return TRUE;
}

int GetTop(SeqStack *S, STACK_DATA_TYPE *val)
{
​    if(IsEmpty(S))
​       return FALSE;
​    *val = S->data[S->top];
​    return TRUE;
}

void Print_Stack(SeqStack *S)
{
​    int i=0;
​    int size=0;
​    if(S->top == -1)
​    {
​       for(i=0; itop; i++)
​       {
​           printf("|_ _ _ _|\n");   //先打印栈上面为空的部分
​       }
​       size = S->top;
​       while(S->top != -1)      //打印有数据的部分
​       {
​           printf("|__ %d __|\n", S->data[S->top]);
​           S->top--;
​       }
​       S->top = size;
​    }
}

int main()
{                 //不建议使用该方法
​    SeqStack *S = InitStack();  //使用指针,动态分配内存
​    IsEmpty(S);
​    int val=0;
​    int i=0;
​    for(i=0; i<3; i++)
​    {
​       Push_Stack(S, i+1);
​    }

​    IsEmpty(S);
​    Print_Stack(S);
​    for(i=0; i<2; i++)
​    {
​       Pop_Stack(S, &val); 
​       printf("%d ", val);
​    }
​    printf("\n");
​    Print_Stack(S);
​    GetTop(S, &val);
​    printf("栈顶元素是:%d\n", val);
​    return 0;
}

输出:

@server:~/test/log/list/stack/array$ gcc -o test test.c -g

@server:~/test/log/list/stack/array$ ./test

栈为空
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|__ 3 __|
|__ 2 __|
|__ 1 __|
3 2
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|_ _ _ _|
|__ 1 __|
栈顶元素是:1

注意:

编译的时候报:error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token

原因:

C语言中是不存在引用的,也就是说C语言中&表示的不是引用,仅仅是取地址符。

解决:

第一种:用指针来取代引用,在主函数中传进地址

第二种:将代码保存成.cpp文件(c++中支持引用)

链栈

栈的链式存储结构成为链栈,是运算受限的单链表。其插入和删除操作只能在表头位置上进行。因此,链栈没有必要像单链表那样附加头结点,栈顶指针top就是链表的头指针。

栈的定义

typedef struct StackNode  //链栈结点
{
​    ElemType data;
​    struct StackNode *next;
}Stack_Node;

typedef struct stack   //链栈结构
{
​    Stack_Node *top;   //栈顶
​    int length;     //长度
}LinkStack;

初始化栈

S->top = NULL;
S->length = 0;

初始化栈顶指针和链栈长度。

是否为空栈

if(S->length == 0)
​    return TRUE;

当链栈长度等于0的时候为空栈,也可以判断 top 是否为 NULL;

入栈

Stack_Node *p = (Stack_Node*)malloc(sizeof(Stack_Node));
p->data = val;
p->next = S->top;  //栈顶赋值给p->next
S->top = p;    //新元素作为栈顶
S->length++;   //链表长度加1

首先将栈顶 top 赋值给 p->next,然后将 p 作为栈顶指针,链栈长度加一。

出栈

Stack_Node *p = S->top;  //标记栈顶
*val = p->data;     //取出栈顶元素
S->top = p->next;    //栈顶下移一个结点
S->length--;      //长度减1
free(p);

获取栈顶

*val = S->top->data;

实例:

#include 
#include 

#define FALSE 0
#define TRUE 1
typedef int ElemType;
typedef struct StackNode  //链栈结点
{
​    ElemType data;
​    struct StackNode *next;
}Stack_Node;

typedef struct stack   //链栈结构
{
​    Stack_Node *top;   //栈顶
​    int length;     //长度
}LinkStack;

void Init_Link_Stack(LinkStack *S)
{
​    S->top = NULL;
​    S->length = 0;
}

int IsEmpty(LinkStack *S)
{
​    if(S->length == 0)
​       return TRUE;
​    else
​       return FALSE;
}

int Push_Stack(LinkStack *S, ElemType val)
{
​    Stack_Node *p = (Stack_Node*)malloc(sizeof(Stack_Node));
​    if(p == NULL)
​    {
​       printf("Memory allocate fail!\n");
​       return FALSE;
​    }
​    p->data = val;
​    p->next = S->top;  //栈顶赋值给p->next
​    S->top = p;    //新元素作为栈顶
​    S->length++;   //链表长度加1
​    return TRUE;
}

int Pop_Stack(LinkStack *S, ElemType *val)
{
​    if(IsEmpty(S) == TRUE)
​    {
​       return FALSE;
​    }
​    Stack_Node *p = S->top;  //标记栈顶
​    *val = p->data;     //取出栈顶元素
​    S->top = p->next;    //栈顶下移一个结点
​    S->length--;      //长度减1
​    free(p);
​    return TRUE;
}

int Get_Top(LinkStack *S, ElemType *val)
{
​    if(IsEmpty(S) == TRUE)
​       return FALSE;
​    *val = S->top->data;
​    return TRUE;
}

void Print_Stack(LinkStack *S)
{
​    int len=0;
​    Stack_Node *p = S->top;  //标记栈顶
​    if(IsEmpty(S))
​    {
​       printf("栈为空\n");
​    }
​    len = S->length;    //标记长度
​    while(S->length != 0)
​    {
​       printf("|__%d__|\n", S->top->data);
​       S->top = S->top->next;
​       S->length--;
​    }
​    S->top = p;     //还原到操作前的栈顶和长度
​    S->length = len;
}

int main()
{
​    int i=0;
​    int val=0;
​    int len=0;
​    LinkStack S;
​    Init_Link_Stack(&S);
​    IsEmpty(&S);
​    printf("请输入入栈长度:");
​    scanf("%d", &len);
​    for(i=0; i

输出:

@server:~/test/log/list/stack/list$ gcc -o liststack liststack.c -g

@server:~/test/log/list/stack/list$ ./liststack

请输入入栈长度:5
|__5__|
|__4__|
|__3__|
|__2__|
|__1__|
请输入出栈长度:3
5 4 3
|__2__|
|__1__|
栈顶元素为:2

参考

https://blog.csdn.net/qq_42451060/article/details/82832246?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

你可能感兴趣的:(数据结构,栈)