(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
目录
初识栈:
(栈的相关操作类似于手枪子弹上膛,装弹时将子弹从上方一个个压入弹夹,开枪时最上面的子弹先被射出)
栈(stack)是限定仅在表尾插入和删除操作的线性表。
允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom)
不含任何数据元素的栈称为空栈
特点:先进后出,后进先出
注意:
1 、栈又被称为后进先出( Last In First Out )的 线性表 ,简称 LIFO 结构
2 、栈的插入操作,称为 进栈 ,也称压栈、入栈( push )
3 、栈的删除操作,称为 出栈 ,也称为弹栈( pop )
顺序栈:
顺序栈是利用一组连续存储单元依次存放栈底到栈顶的数据元素
#define MAX_SIZE 255 typedef struct { int id; char* name; }ElementType; /** 定义栈的顺序存储方式 */ typedef struct SeqStack { ElementType elements[MAX_SIZE]; //顺序栈中用来存放数据元素的数组 int top; //栈顶(数组中的下标),如果为-1则证明栈为空 int length; //当前栈的元素个数 }SeqStack;
初始化栈:
初始化栈时我们需要将栈顶top赋值为-1,这样在后续操作时就可以对top进行加减,便于判断是否为满栈或者空栈
/** 初始化栈 */ void InitSeqStack(SeqStack* seqStack) { seqStack->top = -1; //栈顶指向-1的下标 seqStack->length = 0; }
栈的插入(压栈):
顺序栈的入栈操作只需要将数值赋给对应的数组下标即可(先判断是否可以插入)
/** 向栈中压入元素,返回压入的结果(1/0) */ int PushSeqStack(SeqStack* seqStack, ElementType element) { //判断是否满栈 if (seqStack->top == MAX_SIZE - 1) { printf("满栈,压栈操作失败!"); return 0; } seqStack->top++; //栈顶指针+1,以便加入新的元素 //将新插入的元素赋值给栈顶 seqStack->elements[seqStack->top] = element; seqStack->length++; return 1; }
栈的删除(出栈):
/** 以指针方式返回出栈的元素,返回值为出栈的结果(1/0) */ int PopSeqStack(SeqStack* seqStack, ElementType* element) { if (seqStack->top == -1) { printf("空栈,出栈失败!\n"); return 0; } //返回栈顶指向的元素 *element = seqStack->elements[seqStack->top]; seqStack->top--; seqStack->length--; return 1; }
清空栈:
/** 清空栈 */ void ClearSeqStack(SeqStack* seqStack) { seqStack->top = -1; seqStack->length = 0; }
链栈:
链栈的结构与链表相似
插入与删除等操作都在链表的头部
即:链栈是一个以top为头结点、从栈顶指向栈底的单链表
typedef struct { int id; const char* name; }ElementType; /** 链栈的结点 */ typedef struct StackNode { ElementType data; //结点中保存的元素 struct StackNode* next; //指向下个结点的指针 }StackNode; /** 链栈结构 */ typedef struct LinkedStack { StackNode* top; //栈顶指针 int length; //链栈的长度(元素个数) }LinkedStack;
初始化栈:
void InitLinkedStack(LinkedStack* linkedStack) { linkedStack->top = NULL; linkedStack->length = 0; }
入栈:
入栈时,和单链表(http://t.csdn.cn/yBFit)相似,只需要将新增的数据的next指向栈顶,然后将栈顶指向新增的数据
链栈无需判断是否满栈,因为链式结构几乎为无穷大
/** 压栈并返回结果 */ int PushLinkedStack(LinkedStack* linkedStack, ElementType element) { //创建一个新结点 StackNode* newNode = (StackNode*)malloc(sizeof(StackNode)); newNode->data = element; //新结点的next指向当前的栈顶 newNode->next = linkedStack->top; linkedStack->top = newNode; linkedStack->length++; return 1; }
出栈:
出栈有一点特殊,需要新创建一个结点保存要删除的结点数据,然后当top指向下一个结点后,释放新创建的结点,同时也就释放了要删除的结点
int PopLinkedStack(LinkedStack* linkedStack, ElementType* element) { //判断栈是否为空 if (linkedStack->top == NULL) { printf("空栈,出栈操作失败!\n"); return 0; } //返回栈顶元素 *element = linkedStack->top->data; //创建新结点,记录出栈操作前的栈顶指针 StackNode* node = linkedStack->top; //栈顶指针下移一位 linkedStack->top = linkedStack->top->next; //释放原栈顶空间 free(node); linkedStack->length--; return 1; }
清空栈:
/** 清空栈-遍历栈中的每个元素并释放结点空间 */ void ClearLinkedStack(LinkedStack* linkedStack) { StackNode* tempNode; while (linkedStack->top) { tempNode = linkedStack->top; //栈顶指向下个元素 linkedStack->top = linkedStack->top->next; free(tempNode); linkedStack->length--; } }