顺序表、链表是线性表的两种表示方法,指定的线性表的组织方式,对于不同的读写顺序的线性表,也有不同的定义,例如:
元素按照先入后出的顺序读写的线性表称为栈
元素按照先入先出的顺序读写的线性表称为队列
按照上面的定义,可以组合出四种数据结构:顺序栈、链栈、顺序队列、链队列
对于顺序栈,空间是事先分配好的,一般都会偏大,为了更好地利用顺序栈空间,可以将一个大栈拆分为两个小栈,大栈的两端分为别两个小栈的头部,数据元素从两端向中间插入
本节介绍单向顺序栈和链栈的基本操作实现
栈的构成为:数据域、栈顶指针(对于顺序栈,栈顶指针就是一个整形变量)
顺序栈定义:
typedef struct STACK {
int aidata[ARRAY_SIZE];
int iTop;
}T_Stack, *PT_Stack;
链栈定义:
typedef struct STACK {
int iData;
struct STACK *ptNext;
}T_Stack, *PT_Stack;
对链栈,同前所述,分有无头节点两种情况,这里以常用的有头节点版本为例
栈的主要操作有:
1、创建空栈:PT_Stack createStack(void);
对顺序栈,创建栈就是预先分配一块数据空间和一个栈顶变量,并初始化变量为-1(数据从0位置开始存储)
对链栈,创建栈只需要创建一个头节点(标志性作用)
2、判空/判满:int isEmpty(PT_Stack ptHead); / int isFull(PT_Stack ptStack)
对顺序栈,判空条件为栈顶指针等于-1,判满条件为栈顶指针等于栈大小-1
对链栈,判空条件是头指针的指针域为空,判满条件为内存空间不足
3、入栈:int pushToStack(int iEle, PT_Stack *pptHead);
对顺序栈,入栈时先判满,不满则将栈顶指针加1,写入数据即可
对链栈,入栈时先创建新节点,创建成功则新节点作为第一个数据节点插入链表
4、出栈:int popFromStack(PT_Stack *pptHead);
对于顺序栈,出栈时先判空,不空则先读出数据,然后栈顶指针减1即可
对链栈,出栈时先判空,不空则读出头部数据节点的数据域,并将该节点删除
入栈、出栈操作也可以在链尾进行,但这样需要增加查找链表操作,增加工作量
顺序栈代码:
#include <stdio.h>
#include <stdlib.h>
#define MENU_EXIT 0
#define MENU_PUSH 1
#define MENU_POP 2
#define MENU_PRINT 3
#define ERR -100
typedef struct STACK {
int aidata[ARRAY_SIZE];
int iTop;
}T_Stack, *PT_Stack;
int isEmpty(PT_Stack ptStack)
{
return ptStack->iTop == -1 ? 1 : 0 ;
}
int isFull(PT_Stack ptStack)
{
return ptStack->iTop == ARRAY_SIZE - 1 ? 1 : 0 ;
}
int pushToStack(int iEle, PT_Stack ptStack)
{
if (isFull(ptStack))
return ERR;
ptStack->iTop++;
ptStack->aidata[ptStack->iTop] = iEle;
printf("Push %d to index %d\r\n", iEle, ptStack->iTop);
return iEle;
}
int popFromStack(PT_Stack ptStack)
{
int iEle;
if (isEmpty(ptStack))
return ERR;
iEle = ptStack->aidata[ptStack->iTop];
printf("Pop %d from index %d\r\n", iEle, ptStack->iTop);
ptStack->iTop--;
return iEle;
}
PT_Stack createStack(void)
{
PT_Stack ptStack = NULL;
int i, iNum, iEle;
printf("Enter the num of data\r\n");
scanf_s("%d", &iNum);
if (iNum > ARRAY_SIZE || iNum < 0)
{
printf("Err in the num of data\r\n");
goto done;
}
ptStack = (PT_Stack)malloc(sizeof T_Stack);
ptStack->iTop = -1;
if (!ptStack)
goto done;
printf("Enter your data: ");
for (i = 0; i < iNum; i++)
{
scanf_s("%d", &iEle);
pushToStack(iEle, ptStack);
}
done:
return ptStack;
}
void printStack(PT_Stack ptStack)
{
int i;
if (isEmpty(ptStack))
{
printf("Stack is empty\r\n");
return;
}
printf("\r\n");
for (i = 0; i <= ptStack->iTop; i++)
printf("%d ", ptStack->aidata[i]);
printf("\r\n\r\n");
}
int menu(PT_Stack ptStack)
{
int iNum, iEle;
printf("0 to exit\r\n"
"1 to push\r\n"
"2 to pop\r\n"
"3 to print\r\n");
scanf_s("%d", &iNum);
switch (iNum)
{
case MENU_EXIT:
return -1;
case MENU_PUSH:
printf("Enter the one to be push\r\n");
scanf_s("%d", &iEle);
pushToStack(iEle, ptStack);
break;
case MENU_POP:
popFromStack(ptStack);
break;
case MENU_PRINT:
printStack(ptStack);
break;
}
return 0;
}
int main(void)
{
PT_Stack ptStack;
ptStack = createStack();
if (!ptStack)
return -1;
while (1)
{
if (menu(ptStack) == -1)
break;
}
return 0;
}
链栈代码:
#include <stdio.h>
#include <stdlib.h>
#define MENU_EXIT 0
#define MENU_PUSH 1
#define MENU_POP 2
#define MENU_PRINT 3
#define ERR -100
typedef struct STACK {
int iData;
struct STACK *ptNext;
}T_Stack, *PT_Stack;
int isEmpty(PT_Stack ptHead)
{
return ptHead->ptNext == NULL ? 1 : 0;
}
int pushToStack(int iEle, PT_Stack *pptHead)
{
PT_Stack ptNew = NULL, ptTmp = NULL;
ptNew = (PT_Stack)malloc(sizeof T_Stack);
if (!ptNew)
{
printf("Err in no memory\r\n");
return ERR;
}
ptNew->iData = iEle;
ptTmp = (*pptHead)->ptNext;
if (!ptTmp)
ptNew->ptNext = NULL;
else
ptNew->ptNext = ptTmp;
(*pptHead)->ptNext = ptNew;
return iEle;
}
int popFromStack(PT_Stack *pptHead)
{
PT_Stack ptTmp;
int iEle;
if (isEmpty(*pptHead))
return ERR;
ptTmp = (*pptHead)->ptNext;
iEle = ptTmp->iData;
(*pptHead)->ptNext = ptTmp->ptNext;
free(ptTmp);
//printf("Pop %d\r\n", iEle);
return iEle;
}
PT_Stack createStack(void)
{
PT_Stack ptHead = NULL;
int iNum, i, iEle;
ptHead = (PT_Stack)malloc(sizeof T_Stack);
if (!ptHead)
{
printf("Err in malloc head\r\n");
goto done;
}
ptHead->ptNext = NULL;
printf("Enter the num of data: ");
scanf_s("%d", &iNum);
printf("Enter your data: ");
for (i = 0; i < iNum; i++)
{
scanf_s("%d", &iEle);
pushToStack(iEle, &ptHead);
}
printf("Create a stack with %d nodes\r\n", i);
done:
return ptHead;
}
void printStack(PT_Stack ptHead)
{
PT_Stack ptTmp = ptHead;
if (isEmpty(ptHead))
{
printf("Stack is empty\r\n");
return;
}
printf("\r\n\r\n");
printf("Stack data according to inverted order: ");
while (!isEmpty(ptTmp))
{
ptTmp = ptTmp->ptNext;
printf("%d ", ptTmp->iData);
}
printf("\r\n\r\n");
}
int menu(PT_Stack *pptHead)
{
int iNum, iEle;
printf("0 to exit\r\n"
"1 to push\r\n"
"2 to pop\r\n"
"3 to print\r\n");
scanf_s("%d", &iNum);
switch (iNum)
{
case MENU_EXIT:
return -1;
case MENU_PUSH:
printf("Enter the one to be push\r\n");
scanf_s("%d", &iEle);
pushToStack(iEle, pptHead);
break;
case MENU_POP:
popFromStack(pptHead);
break;
case MENU_PRINT:
printStack(*pptHead);
break;
}
return 0;
}
int main(void)
{
PT_Stack ptHead;
ptHead = createStack();
if (!ptHead)
return -1;
while (1)
{
if (menu(&ptHead) == -1)
break;
}
return 0;
}