[FONT=Courier New]typedef struct ArrayForStacks[/FONT]
[FONT=Courier New]{[/FONT]
[FONT=Courier New] int busy1=0; //номер верхнего свободного элемента для 1 стэка[/FONT]
[FONT=Courier New] int busy2=19; //номер верхнего свободного элемента для 2 стэка[/FONT]
[FONT=Courier New] int elements[20];
} PackedStack;[/FONT]
[FONT=Courier New][/FONT]
[FONT=Courier New]void PushToFirstStack(PackedStack stack, int element)[/FONT]
[FONT=Courier New]{[/FONT]
[FONT=Courier New] if(stack.busy1>=stack.busy2)[/FONT]
[FONT=Courier New] {[/FONT]
[FONT=Courier New] printf("Стэк 1 уже заполнен");[/FONT]
[FONT=Courier New] }[/FONT]
[FONT=Courier New] else[/FONT]
[FONT=Courier New] {[/FONT]
[FONT=Courier New] stack.elements[stack.busy1++]=element;[/FONT]
[FONT=Courier New] }
}[/FONT]
[FONT=Courier New][/FONT]
[FONT=Courier New]int PopFromFirstStack(PackedStack stack)[/FONT]
[FONT=Courier New]{[/FONT]
[FONT=Courier New] return stack.elements[--stack.busy1];
}[/FONT]
[FONT=Courier New][/FONT]
[FONT=Courier New]void PushToSecondStack(PackedStack stack, int element)[/FONT]
[FONT=Courier New]{[/FONT]
[FONT=Courier New]
[FONT=Courier New] if(stack.busy2<=stack.busy1)[/FONT]
[FONT=Courier New] {[/FONT]
[FONT=Courier New] printf("Стэк 2 уже заполнен");[/FONT]
[FONT=Courier New] }[/FONT]
[FONT=Courier New] else[/FONT]
[FONT=Courier New] {[/FONT]
[FONT=Courier New] stack.elements[stack.busy2--]=element;[/FONT]
[FONT=Courier New] }[/FONT]
}[/FONT]
1 массив для хранения 2 стеков
можн
struct{
int top;
int elenents[maxlenth];
};?
Если да то как изменяться методы?
P.s
если есть исходник буду благодарен
Для первого стека верхушка самый первый элемент, для второго будет храниться в переменной.
Если вставляешь в первый стек, то увеличивается длина первого стека и верхушка второго. Перед вставкой все элементы сдвигаются.
Если вставляешь во второй, то увеличивается длина второго стека. Перед вставкой сдвигаются только элементы, начиная с верхушки второго стека.
При удалении - действия обратные.
есть у тебя массив на 80 целых чисел. Для того чтобы он хранил два стека тупо делишь этот массив на две части, т.е. в один стек у тебя "записывается" начиная с нуля и до 39, а во второй, уже начиная с 40 и до 79. Функции push могут иметь вид: void push(char number_of_stack,int value); или т.п. :)
... и соответственно: int pop(char number_of_stack);
Для первого стека верхушка самый первый элемент, для второго будет храниться в переменной.
Если вставляешь в первый стек, то увеличивается длина первого стека и верхушка второго. Перед вставкой все элементы сдвигаются.
Если вставляешь во второй, то увеличивается длина второго стека. Перед вставкой сдвигаются только элементы, начиная с верхушки второго стека.
При удалении - действия обратные.[/QUOTE]
тогда уж сразу надо пользоваться векторами, ведь сдвигать элементы статического массива очень неприятно, хотя бы по скорости. А с векторами куда проще: память выделяется автоматически - сколько надо чисел, чтолько и вставит, а потом и удалит :)
В задаче было сказано про массив.
Как видно, задача дана не для эффективности действий, а для тренировки ума и вывиха моска. :)
Как видно, задача дана не для эффективности действий, а для тренировки ума и вывиха моска. :)[/quote]
Я предлагаю так:
Один массив. Один стэк растёт сверху массива, другой снизу. Одна запись типа int будет хранить длину одного из стэка. Таким образом, тот стэк, которому память в массиве "нужнее" тот и будет её получать. А при делении массива просто на два факт вероятности заполнения обоих массивов не учитывается, таким образом память делится не эффективно. Можно реализовать массив таким образом, чтобы вообще при размещении данных в любой стэк массив не двигать:
Код:
Вообщем, идея понятна думаю....
Можно использовать чётные элементы массива для первого стека, а нечётные для второго.
Можно. Но это опять же разбиение массива пополам. Нет гарантии, что во время работы оба стэка будут эффективно использовать весь массив. Вариант, предложенный выше, учитывает динамику использования массива обоими стэками. Если одному стэку нужно памяти в массиве больше чем второму, он её получает.
Хотя это всё дело вкуса..............
Код:
#include <exception>
const int MAX_STACK = 1024; // максимальный размер стека
typedef int StackItemType;
class StackException: public exception
{
public:
StackException(const char *message="")
: exception(message)
{};
};
class Stack
{
public:
Stack() // Конструктор по умолчанию
{
top1 = -1;
top2 = -1;
bottom1 = -1;
bottom2 = -1;
cnt1 = 0;
cnt2 = 0;
};
// Проверяет пуст ли конкретный стек
bool empty(int stackNo) throw(StackException);
// Добавляет новый элемент на вершину стека stackNo
void push(int stackNo, StackItemType &newItem) throw(StackException);
// Удаляет вершину стека stackNo
void pop(int stackNo, StackItemType *newItem = NULL) throw(StackException);
// Возвращает число элементов стека stackNo
int size(int stackNo) throw(StackException);
// Удаляет все элементы стека stackNo
void erase(int stackNo=0);
private:
StackItemType items[MAX_STACK]; // массив элементов стека
int top1; // вершина стека No 1
int top2; // вершина стека No 2
int bottom1; // дно стека No 1
int bottom2; // дно стека No 2
int cnt1; // текущее число элементов стека No 1
int cnt2; // текущее число элементов стека No 2
};
bool Stack::empty(int stackNo)
{
switch(stackNo)
{
case 1:
return cnt1==0;
case 2 :
return cnt2==0;
default:
throw StackException("StackException : неправильный номер стека(empty)");
}
}
int Stack::size(int stackNo)
{
switch(stackNo)
{
case 1:
return cnt1;
case 2 :
return cnt2;
default:
throw StackException("StackException : неправильный номер стека(size)");
}
}
void Stack::pop(int stackNo, StackItemType *newItem)
{
switch(stackNo)
{
case 1:
if(cnt1>0)
{
if(newItem!=NULL)
*newItem = items[top1];
cnt1--;
if(cnt1==0)
{
top1 = -1;
bottom1 = -1;
}
else
{
top1++;
if(top1==MAX_STACK)
top1 = 0;
}
}
else
{
throw StackException("StackException : стек 1 пуст(pop)");
}
break;
case 2 :
if(cnt2>0)
{
if(newItem!=NULL)
*newItem = items[top2];
cnt2--;
if(cnt2==0)
{
top2 = -1;
bottom2 = -1;
}
else
{
top2--;
if(top2<0)
top2 = MAX_STACK - 1;
}
}
else
{
throw StackException("StackException : cтек 2 пуст(pop)");
}
break;
default:
throw StackException("StackException : неправильный номер стека(pop)");
}
}
void Stack::push(int stackNo, StackItemType &newItem)
{
if(cnt1+cnt2==MAX_STACK)
throw StackException("StackException : стек переполнен");
switch(stackNo)
{
case 1:
cnt1++;
if(cnt1==1)
{
if(cnt2==1)
{
bottom1 = MAX_STACK << 1;
top1 = bottom1;
}
else
{
bottom1 = bottom2 - 1;
if(bottom1 < 0)
bottom1 = MAX_STACK -1;
top1 = bottom1;
}
}
else
{
top1--;
if(top1 < 0)
top1 = MAX_STACK - 1;
}
items[top1] = newItem;
break;
case 2 :
cnt2++;
if(cnt2==1)
{
if(cnt1==1)
{
bottom2 = MAX_STACK << 1;
top2 = bottom2;
}
else
{
bottom1 = bottom2 + 1;
if(bottom2 == MAX_STACK)
bottom2 = 0;
top2 = bottom2;
}
}
else
{
top2++;
if(top2 == MAX_STACK)
top2 = 0;
}
items[top2] = newItem;
break;
default:
throw StackException("StackException : неправильный номер стека(push)");
}
}
void Stack::erase(int stackNo)
{
switch(stackNo)
{
case 1:
top1 = -1;
bottom1 = -1;
cnt1 = 0;
break;
case 2:
top2 = -1;
bottom2 = -1;
cnt2 = 0;
break;
default:
top1 = -1;
top2 = -1;
bottom1 = -1;
bottom2 = -1;
cnt1 = 0;
cnt2 = 0;
}
}
int main()
{
Stack stack;
// ...
// ...
// ...
return 0;
}
const int MAX_STACK = 1024; // максимальный размер стека
typedef int StackItemType;
class StackException: public exception
{
public:
StackException(const char *message="")
: exception(message)
{};
};
class Stack
{
public:
Stack() // Конструктор по умолчанию
{
top1 = -1;
top2 = -1;
bottom1 = -1;
bottom2 = -1;
cnt1 = 0;
cnt2 = 0;
};
// Проверяет пуст ли конкретный стек
bool empty(int stackNo) throw(StackException);
// Добавляет новый элемент на вершину стека stackNo
void push(int stackNo, StackItemType &newItem) throw(StackException);
// Удаляет вершину стека stackNo
void pop(int stackNo, StackItemType *newItem = NULL) throw(StackException);
// Возвращает число элементов стека stackNo
int size(int stackNo) throw(StackException);
// Удаляет все элементы стека stackNo
void erase(int stackNo=0);
private:
StackItemType items[MAX_STACK]; // массив элементов стека
int top1; // вершина стека No 1
int top2; // вершина стека No 2
int bottom1; // дно стека No 1
int bottom2; // дно стека No 2
int cnt1; // текущее число элементов стека No 1
int cnt2; // текущее число элементов стека No 2
};
bool Stack::empty(int stackNo)
{
switch(stackNo)
{
case 1:
return cnt1==0;
case 2 :
return cnt2==0;
default:
throw StackException("StackException : неправильный номер стека(empty)");
}
}
int Stack::size(int stackNo)
{
switch(stackNo)
{
case 1:
return cnt1;
case 2 :
return cnt2;
default:
throw StackException("StackException : неправильный номер стека(size)");
}
}
void Stack::pop(int stackNo, StackItemType *newItem)
{
switch(stackNo)
{
case 1:
if(cnt1>0)
{
if(newItem!=NULL)
*newItem = items[top1];
cnt1--;
if(cnt1==0)
{
top1 = -1;
bottom1 = -1;
}
else
{
top1++;
if(top1==MAX_STACK)
top1 = 0;
}
}
else
{
throw StackException("StackException : стек 1 пуст(pop)");
}
break;
case 2 :
if(cnt2>0)
{
if(newItem!=NULL)
*newItem = items[top2];
cnt2--;
if(cnt2==0)
{
top2 = -1;
bottom2 = -1;
}
else
{
top2--;
if(top2<0)
top2 = MAX_STACK - 1;
}
}
else
{
throw StackException("StackException : cтек 2 пуст(pop)");
}
break;
default:
throw StackException("StackException : неправильный номер стека(pop)");
}
}
void Stack::push(int stackNo, StackItemType &newItem)
{
if(cnt1+cnt2==MAX_STACK)
throw StackException("StackException : стек переполнен");
switch(stackNo)
{
case 1:
cnt1++;
if(cnt1==1)
{
if(cnt2==1)
{
bottom1 = MAX_STACK << 1;
top1 = bottom1;
}
else
{
bottom1 = bottom2 - 1;
if(bottom1 < 0)
bottom1 = MAX_STACK -1;
top1 = bottom1;
}
}
else
{
top1--;
if(top1 < 0)
top1 = MAX_STACK - 1;
}
items[top1] = newItem;
break;
case 2 :
cnt2++;
if(cnt2==1)
{
if(cnt1==1)
{
bottom2 = MAX_STACK << 1;
top2 = bottom2;
}
else
{
bottom1 = bottom2 + 1;
if(bottom2 == MAX_STACK)
bottom2 = 0;
top2 = bottom2;
}
}
else
{
top2++;
if(top2 == MAX_STACK)
top2 = 0;
}
items[top2] = newItem;
break;
default:
throw StackException("StackException : неправильный номер стека(push)");
}
}
void Stack::erase(int stackNo)
{
switch(stackNo)
{
case 1:
top1 = -1;
bottom1 = -1;
cnt1 = 0;
break;
case 2:
top2 = -1;
bottom2 = -1;
cnt2 = 0;
break;
default:
top1 = -1;
top2 = -1;
bottom1 = -1;
bottom2 = -1;
cnt1 = 0;
cnt2 = 0;
}
}
int main()
{
Stack stack;
// ...
// ...
// ...
return 0;
}
можн
struct{
int top;
int elenents[maxlenth];
};?
Если да то как изменяться методы?
P.s
если есть исходник буду благодарен[/QUOTE]
Берешь некую середину массива, один стек "растет" кверху, другой книзу. Лучше, наверное, сделать два набора методов для каждого стека. Только какой смысл в этом - какая разница, два массива или один.