【每日一题】实现一个栈Stack,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)

29 篇文章 0 订阅
20 篇文章 0 订阅

这道题有两种实现方式

方法一:用两个栈来实现

两个栈实现的主要思路是,一个栈存放数据,一个栈存放最小值。

压栈操作:

(1)我们先向S1压栈一个数据

(2)再向S1压入第二个数据,如果此时栈S2为空,并且把需要压栈的元素data和S2的栈顶元素进行比较,如果此时需要压栈的元素小于等于S2栈顶元素,把元素也压入栈2,否则不用管

出栈操作:

判断S1栈顶元素与S2栈顶元素是否相等,相等都出栈,否则出S1

选取最小值:

S2不为空,则直接选取S2的栈顶元素

示意图:

最后插入元素后的图片:

此时最小值元素直接在S2栈顶。

代码实现如下:

#include <iostream>
#include <stack>
using namespace std;
typedef int T;
class stackMin
{
public:
	stackMin()
	{}
	~stackMin()
	{}
	void Push(T data)
	{
		cout << "s1.push(" << data << ")" << endl;
		s1.push(data);
		if (s2.empty() || data < s2.top())
		{
			cout << "s2.push(" << data << ")" << endl;
			s2.push(data);
		}
	}
	void Pop()
	{
		if (s1.top() == s2.top())
		{
			cout << "s2.pop(" << s2.top() << ")" << endl;
			s2.pop();
		}
		cout << "s1.pop(" << s1.top() << ")" << endl;
		s1.pop();
	}
	T Min()
	{
		if (!s2.empty())
		{
			return s2.top();
		}
	}
private:
	stack<T> s1;
	stack<T> s2;
};
int main()
{
	stackMin s1;
	s1.Push(3);
	s1.Push(3);
	s1.Push(8);
	s1.Push(2);
	s1.Push(1);
	int x = s1.Min();
	cout << "最小值为:" << x << endl;
	s1.Pop();
	s1.Pop();
	s1.Pop();
	s1.Pop();
	s1.Pop();
	return 0;
}

运行截图:


方法二:一个栈实现

使用一个栈。元素data入栈时,压入需要的数据data,在压入一个最小值min,min表示当前栈顶到栈底元素最小值;每一次元素出栈时连续出两次,即可达到题目要求。

但是这个方法有一个很大的麻烦,比如压入1,2,3,4,5,6,7,8,9,10。我们每次都要压入1这个元素。

此处便不再给出方法二的代码。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 创建一个空的链,可以定义一个结构体来表示链的节点,包含一个数据域和一个指向下一个节点的指针。操作可以在链的头部插一个新节点,操作可以删除链的头部节点,返回顶元素可以直接返回的头部节点的数据域。 具体实现如下: 1. 定义链节点的结构体: ``` typedef struct StackNode { int data; struct StackNode* next; } StackNode; ``` 2. 定义链的结构体,包含一个指向顶节点的指针: ``` typedef struct LinkStack { StackNode* top; } LinkStack; ``` 3. 创建一个空的链: ``` LinkStack* createLinkStack() { LinkStack* stack = (LinkStack*)malloc(sizeof(LinkStack)); stack->top = NULL; return stack; } ``` 4. 实现操作: ``` void push(LinkStack* stack, int data) { StackNode* newNode = (StackNode*)malloc(sizeof(StackNode)); newNode->data = data; newNode->next = stack->top; stack->top = newNode; } ``` 5. 实现操作: ``` int pop(LinkStack* stack) { if (stack->top == NULL) { printf("Stack is empty.\n"); return -1; } int data = stack->top->data; StackNode* temp = stack->top; stack->top = stack->top->next; free(temp); return data; } ``` 6. 实现返回顶元素操作: ``` int getTop(LinkStack* stack) { if (stack->top == NULL) { printf("Stack is empty.\n"); return -1; } return stack->top->data; } ``` 以上就是创建一个空的链实现返回顶元素的基本算法。 ### 回答2: 链是一种链式存储结构,它是以链表的形式来实现的存储和操作的。创建一个空的链,需要定义一个结构体来表示链节点的数据结构,在C语言中可以使用struct来定义。 struct Node{ int data; struct Node* next; }; 链操作基本包括三个函数,分别是(push)、(pop)和返回顶元素(top)。 1. (push):在链顶插一个新节点。方法是:创建一个新节点,将数据压新节点,将新节点的指针指向顶节点,再将顶指针指向新节点。 void push(struct Node **top, int data){ struct Node *newNode = (struct Node*) malloc(sizeof(struct Node)); newNode->data = data; newNode->next = *top; *top = newNode; } 2. (pop):从链顶删除一个节点。方法是:保存顶节点的数据,将顶指针指向下一个节点,释放顶节点,并返回数据。 int pop(struct Node **top){ if(*top == NULL) return NULL; int data = (*top)->data; struct Node *temp = *top; *top = (*top)->next; free(temp); return data; } 3. 返回顶元素(top):返回顶节点。方法是:返回顶节点的数据。 int top(struct Node **top){ if(*top == NULL) return NULL; return (*top)->data; } 完整代码如下: #include <stdio.h> #include <stdlib.h> struct Node{ int data; struct Node* next; }; void push(struct Node **top, int data){ struct Node *newNode = (struct Node*) malloc(sizeof(struct Node)); newNode->data = data; newNode->next = *top; *top = newNode; } int pop(struct Node **top){ if(*top == NULL) return NULL; int data = (*top)->data; struct Node *temp = *top; *top = (*top)->next; free(temp); return data; } int top(struct Node **top){ if(*top == NULL) return NULL; return (*top)->data; } int main(){ struct Node *top = NULL; push(&top, 1); push(&top, 2); push(&top, 3); printf("%d\n", top(&top)); // 输3 printf("%d\n", pop(&top)); // 输3 printf("%d\n", top(&top)); // 输2 return 0; } ### 回答3: 链是一种基于链表实现。它和普通的结构一样,具有后进先的特点,并且通过链表的形式可以动态地将数据存储在内存中。接下来,我们来创建一个空的链,并实现的基本操作。 - 创建空链的创建可以采用动态内存分配的方式,我们需要定义一个结构体节点,包含数据域和指向下一节点的指针域,用变量top来指示顶元素的位置。创建代码如下: ``` struct Node { int data; Node* next; }; Node *top = NULL; ``` - 是将数据插链表头部,我们需要首先动态地创建一个新节点,将数据存节点中,并将其指针域指向当前的顶元素,最后更新top指针的位置。代码如下: ``` void push(int x) { Node* node = new Node; node->data = x; node->next = top; top = node; } ``` - 是从链表头部删除节点,并更新top指针的位置。我们需要首先判断链是否为空,如果为空,则无法进行操作;如果不为空,则我们需要将top指针指向下一个节点,并将当前节点删除。代码如下: ``` void pop() { if (top == NULL) { cout<<"已空,无法进行操作"<<endl; return; } Node *temp = top; top = top->next; delete temp; } ``` - 返回顶元素 链的top指针存储了当前顶元素的位置,我们可以通过top指针获取顶元素的数。我们需要首先判断链是否为空,如果为空,则无法获取顶元素;如果不为空,则我们可以直接返回top节点的数域。返回顶元素的代码如下: ``` int topElement() { if (top == NULL) { cout<<"为空"<<endl; return -1; } return top->data; } ``` 至此,我们已经实现了链的基本操作,包括创建空链、和返回顶元素。链与普通不同的是,它可以动态地存储数据,节省了静态内存空间的开销。这些操作是链的基础,也是掌握链的关键。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值