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