实现一个栈,要求实现出栈、入栈、返回最小值的时间复杂度为O(1)

  由栈的一些基本操作,很容易使出栈和入栈的时间复杂度为O(1),但是由于入栈数据元素顺序不一定是有序的,故不能直接实现返回最小值的时间复杂度为O(1)。下面提供两种方法:

(一)设置一个特殊的数据结构类型,包括两个栈_data栈和_mindata栈,_data栈和原来的栈操作相同,存储所有的数据,_mindata栈用来存储最小值。

typedef struct Minstack
{
	Stack _data;
	Stack _mindata;
}Minstack;

实例分析:假如入栈元素顺序为1,2,3,1。

1.1 入栈

入栈代码为:

//入栈  第一个元素入两个栈,后面的元素一定会入_data栈,如果data<=_mindata栈的栈顶元素,
//则入_mindata栈;否则不入_mindata栈。
void MinPush(Minstack *ms, SDataType data)
{
	StackPush(&ms->_data, data);
	//第一个元素入_mindata栈
	if (Isempty(ms->_mindata))
	{
		StackPush(&ms->_mindata, data);
	}
	else
	{
		if (data <= TopStack(ms->_mindata))
		{
			StackPop(&ms->_mindata);
			StackPush(&ms->_mindata, data);
		}
	}
}

出入栈的一些操作请戳上篇博客:https://blog.csdn.net/smell201611010513/article/details/82951212

1.2 出栈

_data栈一定会执行出栈操作,但是如果_data栈的栈顶元素和_mindata栈的栈顶元素相同,则_mindata栈也要执行出栈顺序,否则_mindata栈不作任何处理。出栈代码为:

void MinPop(Minstack *ms)
{
	assert(ms->_data.top != 0);
	if (TopStack(ms->_data) ==TopStack( ms->_mindata))
	{
		StackPop(&ms->_data);
		StackPop(&ms->_mindata);
		return;
	}
	StackPop(&ms->_data);
}

1.3 返回最小值

很明显,_mindata栈存储的就是栈内元素的最小值。代码为

SDataType Findmin(Minstack *ms)
{
	return TopStack(ms->_mindata);
}

除栈的一些基本操作外,本题中的完整代码为

#pragma once
#include"Stack.h"
#include<assert.h>
//(一)设置两个栈,一个栈和普通的栈相同,一个栈存储入栈元素中最小的元素。
typedef struct Minstack
{
	Stack _data;
	Stack _mindata;
	int top;
}Minstack;
//初始化
void MinInit(Minstack *ms)
{
	InitStack(&(ms->_data));
	InitStack(&(ms->_mindata));
}
//销毁
void MinDestroy(Minstack *ms)
{
	StackDestroy(&ms->_data);
	StackDestroy(&ms->_mindata);
}
//打印
void MinPrint(Minstack *ms)
{
	PrintS(ms->_data);
	PrintS(ms->_mindata);
}
//入栈  第一个元素入两个栈,后面的元素一定会入_data栈,如果data<=_mindata栈的栈顶元素,则入_mindata栈。
void MinPush(Minstack *ms, SDataType data)
{
	StackPush(&ms->_data, data);
	//第一个元素入_mindata栈
	if (Isempty(ms->_mindata))
	{
		StackPush(&ms->_mindata, data);
	}
	else
	{
		if (data <= TopStack(ms->_mindata))
		{
			StackPop(&ms->_mindata);
			StackPush(&ms->_mindata, data);
		}
	}
}
//出栈  _data栈一定会出栈,比较_data栈的栈顶元素和_mindata栈的栈顶元素,如果前者和后者相等,则_mindata栈也出栈。
void MinPop(Minstack *ms)
{
	assert(ms->_data.top != 0);
	if (TopStack(ms->_data) ==TopStack( ms->_mindata))
	{
		StackPop(&ms->_data);
		StackPop(&ms->_mindata);
		return;
	}
	StackPop(&ms->_data);
}
//找最小值
SDataType Findmin(Minstack *ms)
{
	return TopStack(ms->_mindata);
}
void test3()
{
	Minstack ms;
	MinInit(&ms);
	MinPush(&ms, 1);
	MinPush(&ms, 2);
	MinPush(&ms, 0);
	MinPush(&ms, 3);
	MinPrint(&ms);
	MinPop(&ms);
	MinPrint(&ms);
	printf("%d\n", Findmin(&ms));
	MinDestroy(&ms);
}

头文件“Stack.h”的具体操作代码请戳上篇博客:https://blog.csdn.net/smell201611010513/article/details/82951212

(二)设置一个类似于栈的特殊数据结构类型,包含array和top,其中array中的每个元素是一个包括两个数据元素的结构体。

其数据结构类型为:

#define Min2_size 100
typedef struct Elementenum
{
	SDataType data;
	SDataType min;
}Elementenum;

typedef struct Minstack2
{
	Elementenum array[Min2_size];
	int top;
}Minstack2;

2.1 入栈

假设入栈顺序为1,2,3,1,0.

对于ms2指向的栈,data入栈步骤为:

(1)首先判断ms2指向的栈是否为空,如果为空,将ms2指向的数组的data和min均赋值为data.然后ms2.top加1.

(2)如果不为空,那么data赋值给ms2->array[ms2->top].data,比较data和ms2->array[ms2->top-1].min,如果前者小,则把data赋值给ms2->array[ms2->top].min,否则把ms2->array[ms2->top-1].min赋给ms2->array[ms2->top].min。

(3)将ms2->top加1.

代码为

void Min2Push(Minstack2 *ms2, SDataType data)
{
	if (Isempty2(ms2))
	{
		ms2->array[ms2->top].data = data;
		ms2->array[ms2->top].min = data;
		ms2->top++;
		return;
	}
	if (ms2->array[ms2->top - 1].min < data)
		{
			ms2->array[ms2->top].min = ms2->array[ms2->top - 1].min;
			ms2->array[ms2->top].data = data;
			ms2->top++;
			return;
		}
	ms2->array[ms2->top].min = data;
	ms2->array[ms2->top].data = data;
	ms2->top++;
}

2.2 出栈

出栈的操作和一般的栈相同。代码为

void Min2Pop(Minstack2 *ms2)
{
	ms2->top--;
}

2.3 返回最小值

SDataType Min2min(Minstack2 *ms2)
{
	return ms2->array[ms2->top - 1].min;
}

不过不要忘记对栈进行初始化哦,完整的代码为

#define Min2_size 100
typedef struct Elementenum
{
	SDataType data;
	SDataType min;
}Elementenum;

typedef struct Minstack2
{
	Elementenum array[Min2_size];
	int top;
}Minstack2;
//初始化
void Min2Init(Minstack2 *ms2)
{
	ms2->top = 0;
}
//销毁
void Min2Destroy(Minstack2 *ms2)
{
	ms2->top = 0;
}
//判空  空栈,返回1;非空,返回0.
int Isempty2(Minstack2 *ms2)
{
	if (ms2->top == 0)
	{
		return 1;
	}
	return 0;
}
//打印
void Print2(Minstack2 *ms2)
{
	if (ms2->top == 0)
	{
		printf("空栈\n");
		return;
	}
	for (int i = 0; i < ms2->top;i++)
	{
		printf("%d ", ms2->array[i].data);
	}
	printf("\n%d\n", ms2->array[ms2->top - 1].min);
}
//入栈
void Min2Push(Minstack2 *ms2, SDataType data)
{
	if (Isempty2(ms2))
	{
		ms2->array[ms2->top].data = data;
		ms2->array[ms2->top].min = data;
		ms2->top++;
		return;
	}
	if (ms2->array[ms2->top - 1].min < data)
		{
			ms2->array[ms2->top].min = ms2->array[ms2->top - 1].min;
			ms2->array[ms2->top].data = data;
			ms2->top++;
			return;
		}
	ms2->array[ms2->top].min = data;
	ms2->array[ms2->top].data = data;
	ms2->top++;
}
//出栈 
void Min2Pop(Minstack2 *ms2)
{
	ms2->top--;
}
//找最小元素
SDataType Min2min(Minstack2 *ms2)
{
	return ms2->array[ms2->top - 1].min;
}
void test4()
{
	Minstack2 ms2;
	Min2Init(&ms2);
	Min2Push(&ms2, 1);
	Min2Push(&ms2, 3);
	Min2Push(&ms2,5);
	Min2Push(&ms2, 0);
	Print2(&ms2);
	Min2Pop(&ms2);
	Print2(&ms2);
	printf("%d\n", Min2min(&ms2));
	Min2Destroy(&ms2);
}

猜你喜欢

转载自blog.csdn.net/smell201611010513/article/details/82951274