一個數組實現兩個棧(共享棧)
一個數組實現兩個棧,既然是一個數組變成兩個棧,首先得把你的陣列分成兩部分,
這是一個十個元素的陣列,有幾種方法把他分成兩部分呢?
這麼分!
還是這麼分!
或者這麼分!
言歸正傳,其實分成兩部分還是有兩種分發的,第一種就是我上邊畫的第三種從中間開始分,將你的陣列分成兩個,分別成為一個棧。但是還有一種分發,是比較不容易想到的,那就是將你的資料的資料進行奇偶分開。
下標是紅色的是一個棧,綠色的是另外一個棧。
上邊的將陣列從中間分開,也是有兩種情況的
從中間分開,初始情況下top1和top2都是在中間值,然後從中間開始向兩側增長,
另一種情況是將top1賦值為陣列第一個元素,top2是最後一個元素,從兩側開始往中間增長。
也就是說目前供我們選擇的有三種方法,其實三種方法的實現難度大同小異,實質上區別也不大,但是最好的方法確是我最後介紹的,讓陣列從兩側開始往中間增長的。現在設想一下,你的陣列初始大小為20也就是說你每個棧分到的大下是10個數據的空間,假如你現在要往其中一個棧中存入10000個數據,記憶體不夠是不是需要擴充套件,你擴充套件必定是擴充套件整個陣列,一個棧中放了10個數據,另一個放了10000個數據,會導致你的空間利用率比較低,但是第三種情況就很好的避免了這種情況,只有在你兩個棧頂指標遇到的時候才會認為你的空間使用完了,進行空間擴容。
typedefstructSNode{
ElementType *Data;
Position Top1, Top2;
int MaxSize;
}*Stack;
先建立結構體,結構體中包含你的陣列,以及兩個棧的指標,還有你在動態分配的時候的陣列的初始最大空間。
Stack CreateStack(int MaxSize)
{
Stack L = (Stack)malloc(sizeof(struct SNode));
L->Data = (ElementType*)malloc(sizeof(ElementType)*MaxSize);
L->Top1 = -1;
L->Top2 = MaxSize;
L->MaxSize = MaxSize;
return L;
}
創造結構體函式,給你的結構體分配空間以及初始化。
void Push(Stack S, ElementType X, int Tag){
if (S->Top1 == S->Top2 - 1){
printf("Stack Full\n");
return ;
}
if (Tag == 1)
S->Data[++S->Top1] = X;
else
S->Data[--S->Top2] = X;
return ;
}
這是push函式,在push的時候,之前的push需要穿入棧,以及你要插入的值,這裡需要再加入一個標誌,來判斷你是給你左邊的棧插入元素,還是給右邊的棧插入元素。
ElementType Pop(Stack S, int Tag){
if (Tag == 1){
if (S->Top1 == -1){
printf("Stack %d Empty\n", Tag);
return -1;
}
else
return S->Data[S->Top1--];
}
else if (S->Top2 == S->MaxSize){
printf("Stack %d Empty\n", Tag);
return -1;
}
else return S->Data[S->Top2++];
}
Pop也是同理,需要多傳入一個標誌引數,來判斷你是想出哪個棧中的資料。
無論在哪個位置當你的S->Top1 == S->Top2 - 1的時候,就代表你的陣列已經滿了。
當你的陣列擴充之後要將你的後邊棧的資料全部搬到當前陣列的最後部分。
void IncreaseArea(Stack S, int MaxSize)
{
ElementType N;
S->Top2 = MaxSize;
S->Data = (ElementType*)malloc(sizeof(ElementType)*MaxSize*2);
N = MaxSize * 2;
while (S->Top2 != S->Top1)
{
S->Data[N] = S->Data[S->Top2];
N--;
S->Top2--;
}
S->Top2 = N;
return;
}
分配好空間之後,將你的top2指向之前陣列的最後邊,也就是你後邊棧的第一個元素位置,然後將N指向擴充後的最後位置。這時候一一對應將資料複製過去,然後將N和TOP2都往後移動。直到TOP2指向了最後一個元素。然後將top2指向當前棧的棧頂元素就結束了。