1.什么是栈
栈(stack)是仅能在表尾进行删除和增加的线性表
对栈来说,表尾段叫做栈顶。相应的表头段叫做栈尾
像洗盘子的时候叠盘子和取盘子就像栈的使用。
栈又可以分为顺序栈和链栈
2.顺序栈的表示和实现
2.1栈的定义
#define MAXSIZE 300
typedef struct
{
int StackSize; //栈可用的最大容量
SElemType *top; //栈顶指针
SElemType *base; //栈尾指针
}
2.2栈的初始化
步骤:
1>把一个大小为MAXSIZE的数组空间分配给栈,使base指向这段空间的基地址,即栈底
2>把top指向base代表栈此时为空
3>将栈的最大容量置为MAXSIZE
int InitStack (SqStacak &S)
{
S.base = new SElemType[MAXSIZE];//1>把一个大小为MAXSIZE的数组空间分配给栈,使base指向这段空间的基地址,即栈底
if(!S.base) exit (ERROR);
S.top = S.base;//把top指向base代表栈此时为空
S.stacksize = MAXSIZE;//将栈的最大容量置为MAXSIZE
return OK;
}
2.2入栈
步骤:
1>判断栈是否满,满返回ERROR。
2>不满就把新元素加到栈顶,top值加一
int Push (SqStack &s,SElemType e)
{
if(s.top-s.base == MAXSIZE)//1>判断栈是否满,满返回ERROR。
return ERROR;
else
*S.top++ = e;//2>不满就把新元素加到栈顶,top值加一
return OK;
}
2.3出栈
步骤:
1>判断栈是否为空,是则返回ERROR
2>不为空就栈顶指针减一并使栈顶元素出栈
int Pop(SqStack &S,SElemType &e)
{
if(S.top == S.base) return ERROR;//判断栈是否为空,是则返回ERROR
else e = *S.top--;//不为空就栈顶指针减一并使栈顶元素出栈
return OK;
}
2.4获取栈顶
步骤和出栈一样的,只不过不用栈顶指针减一
int GetTop(SqStack S)
{
if(S.top == S.base) return ERROR;
return *(S.top-1);//减一是因为上面提到过的top总是在栈顶上面那一个位置
}
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 5 /* 栈最大容量 */
#define Empty 0 /* 空 */
#define Full 1 /* 满 */
#define Avail -1 /* 可用 */
typedef struct sta
{
int *top; /* 栈顶指针 */
int *bottom; /* 栈底指针 */
int stack_size; /* 栈的最大容量 */
}stack;
stack Push (stack p); /* 入栈 */
void DisplyStack (stack p); /* 遍历栈中元素 */
stack Pop (stack p); /* 出栈 */
stack InitStack (stack p); /* 初始化栈 */
int StackEmpty (stack p); /* 判断栈是否为空 */
int StackFull (stack p); /* 判断栈是否为满 */
int main()
{
stack p;
char ch;
p.stack_size = MAX_SIZE;
p = InitStack (p); /* 初始化栈 */
printf("Do you want to push to stack?(Y/N)");
scanf(" %c", &ch);
while (ch == 'Y' || ch == 'y')
{
p = Push (p); /* 入栈 */
DisplyStack (p);/* 打印栈中元素 */
printf("Do you want to push to stack?(Y/N)");
scanf(" %c", &ch);
}
printf("Do you want to pop (Y/N)");
scanf(" %c", &ch);
while (ch == 'Y' || ch == 'y')
{
p = Pop (p);
DisplyStack (p);
printf("Do you want to pop (Y/N)");
scanf(" %c", &ch);
}
return 0;
}
/* Function:判断栈是否为空 */
int StackEmpty (stack p)
{
if (p.top == p.bottom)
{
return Empty;
}
else
{
return Avail;
}
}
/* Function:判断栈是否为满 */
int StackFull (stack p)
{
if (p.top - p.bottom == p.stack_size)
{
return Full;
}
else
{
return Avail;
}
}
/* Function:入栈 */
stack Push (stack p)
{
int data;
if (StackFull(p) == Full)
{
printf("栈空间已满,无法入栈");
return p;
}
printf("Please input data");
scanf("%d", &data);
*p.top = data;
p.top++;
return p;
}
/* Function:出栈 */
stack Pop (stack p)
{
if (StackEmpty(p) == Empty)
{
printf("栈为空栈,无法出栈 ");
return p;
}
p.top--;
printf("出栈元素为:%d\n", *p.top);
return p;
}
/* Function:栈的初始化 */
stack InitStack (stack p)
{
p.bottom = (int *)malloc(p.stack_size * sizeof(int));
if (p.bottom == NULL)
{
printf("初始化栈失败\n");
exit(0);
}
p.top = p.bottom;
p.stack_size = MAX_SIZE;
return p;
}
/* Function:遍历栈中元素,从栈顶到栈底*/
void DisplyStack (stack p)
{
if (StackEmpty(p) == Empty)
{
printf("栈为空栈,无法遍历\n");
return;
}
printf("栈中元素为:");
printf("顶端[");
while (p.top != p.bottom)
{
p.top--;
printf("%d-", *p.top);
}
printf("]底端\n");
}
3.链栈的表示和实现
因为顺序栈在满员是重新增加容量可以实现但是很复杂,所以我们用链栈来完善这个功能
3.1栈的表示
typedef struck
{
Elemtype data;
struct StackNode *next;
}StackNode.*LinkStacak;
3.2栈的初始化
链栈的初始化就是构造一个空栈,因为没必要在搞头结点,所以就让栈顶指针置空即可
int InitStack(LinkStack &S)
{
S = NULL;//构造一个空栈
return OK;
}
3.3入栈
因为它用链表表示的很方便,所以不需要再判断是否为满
直接分配一个新结点即可
步骤:
1>为新元素e分配空间,用指针p指向。
2>将新结点数据域置为e
3>将新结点插入栈顶
4>修改栈顶指针为p
int Push(LinkStack &S,SElemType e)
{
p = new StackNode;//生成新结点
p->data = e;//为新元素e分配空间,
p->node = S;//将新结点插入栈顶
S = p;//修改栈顶指针为p
return OK;
}
3.4出栈
需要判断是否为空,并且出了后就要释放掉原有的栈顶空间
步骤:
1>判断是否为空
2>将栈顶元素给e
3>临时保存栈顶元素的空间,以备释放
4>修改栈顶指针,指向新的栈顶元素
5>释放原有的
int Pop(LinkList &S,SELemType &e)
{
if(S == NULL)return ERROR;//判断是否为空
e = S->data;//将栈顶元素给e
p = S;//临时保存栈顶元素的空间,以备释放
S= S->next;//修改栈顶指针,指向新的栈顶元素
delete P;//释放原有的
return OK;
}
3.5取栈顶元素
和顺序栈有关的操作没啥区别
int GetTop(LinkStack S)
{
if(S! = NUll) return S->data;
}
#include <iostream>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node;
typedef struct stack{
Node *top; /**书本写法是:加一个bottom,个人感觉没什么用,反而加一个count用于表示节点数会更好*/
int count;
}Link_Stack;
/**创建一个空栈*/
Link_Stack * Creat_stack()
{
Link_Stack *p;
p = new Link_Stack; /**这一步不要忘!需要给p创建空间*/
p->count = 0;
p->top = NULL;
return p;
}
/**入栈操作:push*/
Link_Stack * Push_stack(Link_Stack *p,int elem)
{
if(NULL == p)
return NULL;
Node *temp;
temp = new Node;
temp->data = elem;
temp->next = p->top; /**注意这里和队列的入队操作不同,next指向不同,为了方便出栈操作*/
p->top = temp;
p->count += 1;
return p;
}
/**出栈操作:pop*/
Link_Stack * Pop_stack(Link_Stack *p)
{
Node *temp;
temp = p->top;
if(NULL == p->top)
{
cout << "The stack is empty." << endl;
return p;
}
else{
p->top = p->top->next; /** temp = temp->next; 千万不能这么写,看看下一步是什么?*/
delete temp;
p->count -= 1;
return p;
}
}
/**栈的遍历:输出栈*/
int Show_stack(Link_Stack *p)
{
Node *temp;
temp = p->top;
if(NULL == p->top)
{
cout << "The stack is empty." << endl;
return 0;
}
while(NULL != temp)
{
cout << temp->data << ' ';
temp = temp->next;
}
cout << endl;
return 0;
}
int main()
{
int i = 5;
int elem;
Link_Stack *p;
p = Creat_stack();
while(i--)
{
cin >> elem;
Push_stack(p,elem);
}
cout << "空栈插入5个元素后:" << endl;
Show_stack(p);
cout << "删除3个元素后:" << endl;
for(i = 3;i--;)
{
Pop_stack(p);
}
Show_stack(p);
cout << "count:" << p->count << endl;
cout << "删除2个元素后:" << endl;
for(i = 2;i--;)
{
Pop_stack(p);
}
Show_stack(p);
cout << "count:" << p->count << endl;
Push_stack(p,6);
cout << "插入元素6后:" << endl;
Show_stack(p);
cout << "count:" << p->count << endl;
return 0;
}