数据结构与算法----顺序栈与链栈

栈(Stack):是限制在表的一端进行插入和删除操作的线性表。又称为后进先出LIFO (Last In First Out)或先进后出FILO(First In Last Out)线性表。
栈顶(Top)∶允许进行插入、删除操作的一端,又称为表尾。用栈顶指针(top)来指示栈顶元素。
栈底(Bottom):是固定端,又称为表头。空栈:当表中没有元素时称为空栈。
 

顺序栈

#include <iostream>
 
using namespace std;
 
#define MAX 100
 
//顺序栈的定义 
typedef struct 
{
	int *base;
	int *top;
	int stacksize;
}SqStack;
 
//初始化
int InitStack(SqStack &S) 
{
	S.base = new int[MAX]; // 为顺序栈动态分配一个最大容量为MAX的数组空间
	if (!S.base) 
	{
		return 0;
	}
	
	S.top = S.base;//初始化将栈置空,就是让头指针指向尾指针,从语句上讲就是把尾指针的值赋值给头指针 
	S.stacksize = MAX;
	
	return 1;
}
 
//入栈
int Push_S(SqStack &S, int e) 
{
	//将元素e入栈 
	if (S.top - S.base == S.stacksize) // 判断栈是否满 
	{
		return 0;
	}
	*S.top++ = e;   // *S.top=e;  S.top++;
	
	return 1;
}
 
//出栈
int Pop_S(SqStack &S, int &e) 
{
	//用e返回出栈的元素
	if (S.top == S.base) // 判断栈是否为空 
	{                
		return 0;
	}
	e = *--S.top;   // --S.top;e=*S.top;
	
	return 1;
}
 
// 取栈顶元素
int GetTop( SqStack S, int &e)  
{
	if (S.top == S.base)
		return 0; 	// 栈空
	
	e = *(S.top - 1);
	
	return 1;
}
 
int main()
{
	SqStack S;
 
	if (InitStack(S)) 
	{
		printf("顺序栈初始化成功!\n");
	}
	else 
	{
		printf("顺序栈初始化失败!\n");
	}
 
	int loop = 1;
	int e1;
	int i = 1;
	
	// 入栈
	printf("请输入入栈元素(输入0终止):\n");
	while (loop) 
	{
		printf("请输入第%d个元素值:",i++);
		scanf("%d", &e1);
		if (e1 != 0) 
		{
			Push_S(S,e1);
 
		}
		else if (e1 == 0) 
		{
			loop = 0;
		}
	}
 
	// 取栈顶元素
	int e2;
	GetTop(S, e2);
	printf("栈顶元素是:%d\n", e2);
 
	// 出栈
	int e3; int j = 1;
	while (S.top != S.base)
	{
		Pop_S(S, e3);
		printf("第%d个出栈的元素是:%d\n",j++,e3);
	}
	
	system("pause");
	
	return 0;
}

链栈
​ 链栈是一种特殊的线性链表,使使用链式存储结构的栈,链栈也有栈顶栈底,同样是一种后进先出(LIFO)的数据结构

链栈定义
​ 链栈需要定义两个结构体,LinkStackNode 用来定义链栈节点的类型,存放节点的数据和下一节点的 next 指针

​ LinkStack 结构体用来定义链栈的结构,存放 top 栈顶指针和链栈的总长度

typedef struct LinkStackNode {
    int data;
    LinkStackNode *next;
}LinkStackNode;

typedef struct LinkStack {
    LinkStackNode *top;
    int length;
}LinkStack;

创建链栈
​ 创建链栈的过程就是定义 LinkStack 变量并为其分配内存,再让栈顶指针指空,栈的长度归 0

LinkStack * CreateStack() {
    LinkStack *p;
    p = (LinkStack *)malloc(sizeof(LinkStack));
    p->length = 0;
    p->top = NULL;
    return p;
}

判断栈是否为空
int IsEmpty(LinkStack *p) {
    if (p->length == 0)
        return 1;
    else
        return 0;
}

入栈
​ 因为栈的本质是一种后入先出的数据结构,所以所有的操作都要在栈顶进行。入栈操作即定义新的 LinkStackNode 并为其分配内存,给他的数据域赋值,使新节点的 next 指向原栈顶处的节点,在使新入节点成为新的栈顶结点,栈的长度 +1

LinkStack *PushStack(LinkStack *p, int d) {
    if (p == NULL)
        return NULL;
    LinkStackNode *temp;
    temp = (LinkStackNode *)malloc(sizeof(LinkStackNode));
    temp->data = d;
    temp->next = p->top;
    p->top = temp;
    p->length++;
    return p;
}

出栈
​ 出栈需要先判断栈是否为空,再将栈顶指针指向原栈顶节点的 next,释放原栈顶节点的内存,栈的长度 -1

LinkStack *PopStack(LinkStack *p) {
    LinkStackNode *temp;
    temp = p->top;
    if (p->top == NULL || IsEmpty(p) == 1) {
        cout << "this stack is EMPTY !" << endl;
        return p;
    }
    else {
        p->top = p->top->next;
        free(temp);
        p->length--;
        return p;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
打印栈
​ 打印栈同样先检测栈是否为空,然后在遍历栈的同时打印每个节点的数据

int ShowStack(LinkStack *p) {
    LinkStackNode *temp;
    temp = p->top;
    if (p->top == NULL || IsEmpty(p) == 1) {
        cout << "this stack is EMPTY !" << endl;
        return 0;
    }
    while (temp != NULL) {
        cout << temp->data << ' ';
        temp = temp->next;
    }
    cout << endl;
    return 0;
}
 

上一篇:栈的链式存储的实现


下一篇:数据结构线性表 - 链栈练习Demo