当前位置:   article > 正文

【数据结构】栈的两种实现方式和基本操作_栈的操作实现

栈的操作实现

栈的特性

栈是一种只限定在表尾进行插入和删除操作的线性表,允许插入和删除的一段称作栈顶(top),另一端称为栈底,不含任何数据元素的称为空栈,栈的特性是后进先出

栈模型
栈的存储方式有两种,一种是顺序栈一种是链表栈
顺序栈利用一组地址连续的存储单元存放自栈底到栈顶的元素,同时附设一个指针(top)指示当前栈顶的位置。

#define MaxSize 100 //定义栈中元素的最大个数
typedef struct Stack {
    int data[MaxSize]; //存放栈中的元素
    int top; 		   //栈顶指针
}Stack;
  • 1
  • 2
  • 3
  • 4
  • 5

链表栈常采用单链表实现,并且所有操作都是在单链表的表头进行。

typedef struct StackNode{
    int data; //数据域
    struct LinkNode *next; //指针域
}StackNode; 
  • 1
  • 2
  • 3
  • 4

本文介绍顺序栈的实现和链表栈的实现,其中链表栈和单链表差不多,可参考此文

栈的数组实现

  • 初始化栈
    void InitStack(Stack* stack);
  • 判断空栈
    bool isEmpty(Stack* stack);
  • 进栈
    void Push(Stack* stack, int x);
  • 出栈
    void Pop(Stack* stack,int *x);
  • 读栈顶元素
    int GetTop(Stack* stack);
  • 遍历栈
    void Print(Stack stack);
  • 销毁栈
    void Destroy(Stack* stack);

初始化栈

将栈顶指针设置为-1就可以了(空栈)。

void InitStack(Stack* stack)
{
	stack->top = -1;
}
  • 1
  • 2
  • 3
  • 4

判断空栈

栈顶指针为-1就是空栈,大于-1就不是空栈。

bool isEmpty(Stack* stack)
{
	if (stack->top == -1)
		return true;
	else
		return false;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

读栈顶元素

int GetTop(Stack* stack)
{
	if (isEmpty(stack))
	{
		printf("栈空\n");
		return -1;
	}
	else
		return stack->data[stack->top];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

遍历栈

注意:遍历栈如果像我这样写,参数要注意不可是Stack*stack,不然遍历之后栈就空了。

void Print(Stack stack)
{
	while (stack->top != -1)
	{
		printf("%4d", stack->data[stack->top--]);
	}
	printf("\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

销毁栈

栈的销毁令S.top = -1即可

void Destroy(Stack* stack)
{
	stack->top = -1;
}

  • 1
  • 2
  • 3
  • 4
  • 5

进栈

进栈的时候栈顶指针先上移,然后在放入元素

void Push(Stack* stack, int x)
{
	if (stack->top == MaxSize - 1)
	{
		printf("栈已经满了\n");
		return;
	}
	stack->data[++stack->top] = x;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

出栈

出的时候栈顶指针下移一位即可

void Pop(Stack* stack,int* x)
{
	if (stack->top ==  - 1)
	{
		printf("栈已经空了\n");
		return;
	}
	*x=stack->data[stack->top--] ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

测试
在这里插入图片描述

栈的链表实现

typedef struct Node
{
	int element;
	ptrToNode next;
}Node;
typedef struct Node* ptrToNode;
typedef ptrToNode Stack;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 判断是否为空栈
    int IsEmpty(Stack s);
  • 创建一个栈
    Stack CreatStack();
  • 销毁一个栈
    void DestroyStack(Stack s);
  • 清空栈
    void MakeEmpty(Stack s);
  • 进栈
    void Push(int x, Stack s);
  • 出栈
    void Pop(Stack s);
  • 显示栈顶元素
    int Top(Stack s);
  • 打印栈的所有元素
    void ShowStack(Stack s);

判断空栈

int IsEmpty(Stack s)
{
	return s->next==NULL;
}
  • 1
  • 2
  • 3
  • 4

s不是栈顶元素,s是链表的表头,第一个元素是表头后的元素s->next。

创建一个空栈

Stack CreatStack()
{
	Stack s;
	s = malloc(sizeof(Node));
	if (s == NULL)
		printf("创建栈失败\n");
	else
		s->next = NULL;
	//MakeEmpty(s);
	return s;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

进栈

元素的进栈操作就相当于单链表的头插法。

void Push(int x, Stack s)
{
	ptrToNode tempNode;
	tempNode = malloc(sizeof(Node));
	if (tempNode == NULL)
		printf("创建临时节点失败\n");
	else
	{
		tempNode->element = x;
		tempNode->next = s->next;
		s->next = tempNode;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

出栈

出栈操作就相当于单链表的头删操作。

void Pop(Stack s)
{
	ptrToNode firstNode;
	if (IsEmpty(s))
		printf("这是一个空栈\n");
	else
	{
		firstNode = s->next;
		s->next = s->next->next;
		free(firstNode);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

清空栈

连续将栈顶元素弹出,直到为空栈

void MakeEmpty(Stack s)
{
	if (s == NULL)
		printf("请先使用CreateStack()创建一个栈\n");
	else
	{
		while (!IsEmpty(s))
		{
			Pop(s);
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

总结

在本篇文章中,我们详细探讨了两种实现栈的方法:循序栈和链表栈。

循序栈的优点在于其实现简单且效率高。然而,它的缺点在于需要预先确定栈的最大容量,这限制了它的灵活性。如果栈的实际大小超过了最大容量,将会导致栈溢出。

链表栈的优点在于其灵活性。由于链表节点的内存空间是动态分配的,所以链表栈的大小只受限于可用内存的大小。此外,链表栈还可以方便地进行扩容和缩容。然而,链表栈的缺点在于其实现相对复杂。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/635460
推荐阅读
相关标签
  

闽ICP备14008679号