数据结构:栈


栈(stack)是一个特殊的线性表,是限定仅在一端通常是表尾)进行插入和删除操作的线性表。又称为后进先出(Last In First Out)的线性表,简称LIFO结构。

1.栈的相关概念

栈是仅在表尾进行插入、删除操作的线性表。
表尾(即an端)称为栈顶Top;表头(即ah端)称为栈底Base
插入元素到栈顶(即表尾)的操作,称为入栈。
从栈顶(即表尾)删除最后一个元素的操作,称为出栈。

栈的相关概念描述
定义限定只能在表的一端进行插入和删除运算的线性表(只能在栈顶操作)
逻辑结构与同线性表相同,仍为一对一关系。
存储结构用顺序栈或链栈存储均可,但以顺序栈更常见
运算规则只能在栈顶运算,且访问结点时依照进先出 (LIFO) 的原则。
实现方式关键是编写入栈和出栈函数,具体实现依顺序栈或链栈的不同而不同。

2.栈和一般线性表的区别

栈与一般线性表的区别:仅在于运算规则不同。

一般线性表
逻辑结构:一对一逻辑结构:一对一
存储结构:顺序表、链表存储结构:顺序栈、链栈
随机存取运算规则:后进先出 (LIFO)

3.栈的抽象数据类型与类型定义

操作名称描述初始条件操作结果
InitStack(&S)初始化操作栈S已存在构造一个空栈S
GetTop(S, &e)取栈顶元素栈S已存在且非空用e返回S的栈顶元素
DestroyStack(&S)销毁栈操作栈S已存在栈S被销毁
ClearStack(&S)栈置空操作栈S已存在将S清为空栈
Push(&S, e)入栈操作栈S已存在插入元素e为新的栈顶元素
Pop(&s, &e)出栈操作栈S已存在且非空删除S的栈顶元素an,并用e返回其值
StackEmpty(S)判定S是否为空栈栈S已存在若栈S为空栈,则返回TRUE,否则FALSE
StackLength(S)求栈的长度栈S已存在返回S的元素个数,即栈的长度

4.顺序栈的表示和实现

4.1顺序栈的定义

存储方式:同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈到栈顶的数据元素。栈底一般在低地址端。

  • 附设top指针,指示栈顶元素在顺序栈中的位置。
  • 另设base指针,指示栈底元素在顺序栈中的位置。
//顺序栈的定义  
#define Max_Size 100  
typedef int SElemType;  
typedef struct {  
    SElemType* top;     //栈顶指针  
    SElemType* base;    //栈底指针  
    int stacksize;      //栈的最大可用容量  
}SqStack;

4.2顺序栈的初始化

//顺序栈的初始化  
bool InitSqStack(SqStack* S) {  
    //为栈分配一个内存空间  
    S->base = (SElemType)malloc(Max_Size*sizeof(SElemType));  
  
    if(!S->base) {  
        return false;  
    }  
  
    S->top = S->base;  
    S->stacksize = Max_Size;  
  
    return true;  
}  
  
//判断栈是否为空  
bool StackEmpty(SqStack* S) {  
    if(S->base == S->top) {  
        return true;  
    }  
    return  false;  
}

4.3一些补充算法

4.3.1求顺组栈的长度

int StackLength(SqStack* S) {  
    return S->top - S->base;  
}

4.3.2清空顺序栈

//清空顺序栈  
void CleerStack(SqStack* S) {  
    if(S->base) {  
        S->top = S->base;  
    }  
}

4.3.3销毁顺序栈

//销毁顺序栈  
void DestoryStack(SqStack* S) {  
    if(S->base) {  
        S->stacksize = 0;  
        S->top = S->base = NULL;  
    }  
}

4.4顺序栈入栈

  1. 判断是否栈满,若满则出错(上溢)
  2. 元素e压入栈顶
  3. 栈顶指针加1
void Push(SqStack* S,SElemType e) {  
    if(S->top - S->base == S->stacksize) {  
        return;  
    }  
    S->top++ = e;  
}

4.5顺序栈的出栈

  1. 判断是否栈空,若空则出错(下溢)
  2. 获取栈顶元素e
  3. 栈顶指针减1
//顺序栈的出栈  
void Pop(SqStack* S, SElemType e) {  
    if(S->top == S->base) {  
        return;  
    }  
    e = --S->top;  
}

5.链栈的表示和实现

5.1链栈的表示

链栈是运算受限的单链表,只能在链表头部进行操作

typedef struct StackNode{
	SElemType data;
	struct StackNode *next;
}StackNode,*LinkStack;
LinkStack S;
  • 链表的头指针就是栈顶
  • 不需要头结点
  • 基本不存在栈满的情况
  • 空栈相当于头指针指向空
  • 插入和删除仅在栈顶处执行

5.2链栈的初始化

void InitStack(LinkStack &S )
//构造一个空栈,栈顶指针置为空
	S=NULL;
}

5.3判断链栈是否为空

// 判断链栈是否为空的函数
Status IsEmpty(LinkStack S) {
    return S->top == NULL; // 如果栈顶指针为NULL,则栈为空
}

5.4链栈的入栈操作

// 链栈的入栈操作
Status Push(LinkStack S, SElemType e) {
    LinkNode* new_node = (LinkNode*)malloc(sizeof(LinkNode)); // 创建新节点
    if (!new_node) {
        return ERROR; // 内存分配失败
    }
    new_node->data = e; // 将元素e赋值给新节点的数据部分
    new_node->next = S->top; // 新节点的next指向原栈顶
    S->top = new_node; // 更新栈顶为新节点
    return OK; // 入栈成功
}

5.5链栈的出栈操作

// 链栈的出栈操作
Status Pop(LinkStack S, SElemType* e) {
    if (IsEmpty(S)) {
        return ERROR; // 如果栈为空,出栈失败
    }
    LinkNode* temp = S->top; // 保存栈顶节点
    S->top = S->top->next; // 将栈顶指向下一个节点
    *e = temp->data; // 将出栈元素赋值给e
    free(temp); // 释放原栈顶节点的内存
    return OK; // 出栈成功
}
posted @ 2024-07-26 17:08  写代码的大学生  阅读(16)  评论(0编辑  收藏  举报  来源