1. 程式人生 > >實現一個棧,要求實現出棧、入棧、返回最小值的時間複雜度為O(1)

實現一個棧,要求實現出棧、入棧、返回最小值的時間複雜度為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);
		}
	}
}

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);
}

(二)設定一個類似於棧的特殊資料結構型別,包含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);
}