A language has not array as a data type but it has stack as a data type and one can declare stack's; and push, pop and isempty operations are defined.
So how can we implement array using two stacks and above operations?
Horribly inefficient - but:
Stack 1 Contains the details
Stack 2 is empty.
To go through the array, Pop Stack 1 , when you want the next one, push the previous one into stack 2 and pop stack 1 again. Repeat until 'isempty'.
If you want the Nth value, pop the not empty stack N times while pushing the unneeded ones into the other stack. Then when you're done playing with it, empty it into the other stack. Note that this;ll flip the order.
With two stacks you can get some sort of random access (which is what you're interested in an array) like this:
Put everything on a stack.
Every time you have to access something that's not the top of the stack (pop), you pop all elements from this stack and push them in order to the second one.
By passing elements from one stack to another you simulate iteration.
First element of array is a bottom of stack1;
Last element of array is a bottom of stack2;
Current element of array is a top of stack1;
Iterates through the array by shifting the elements of the stack1 to stack2(move to the begin) and vice versa (move to end).
#include <stdio.h>
#include <stdlib.h>
#define Type int
#define DefaultValue 0
#define bool int
typedef struct stack{
Type *stack;
Type *sp;
size_t size;
} Stack;
Stack* Stack_make(size_t size){
Stack *s;
s = (Stack*)malloc(sizeof(Stack));
s->stack = (Type*)malloc(sizeof(Type)*size);
s->sp = s->stack -1;
s->size = size;
return s;
}
bool Stack_empty(Stack *s){//isempty
return s->sp < s->stack;
}
void Stack_push(Stack *s, Type value){
if(s->sp >= s->stack + s->size -1){
fprintf(stderr, "stack over flow\n");
exit(-1);
}
*(++s->sp) = value;
}
Type Stack_pop(Stack *s){
if(Stack_empty(s)){
fprintf(stderr, "stack is empty\n");
exit(-2);
}
return *s->sp--;
}
void Stack_free(Stack *s){
if(s!=NULL){
free(s->stack);
free(s);
}
}
typedef struct array {
Stack *front;
Stack *back;
size_t size;
size_t index;
} Array;
Array* Array_make(size_t size){
Array *a;
int i;
a = (Array*)malloc(sizeof(Array));
a->front = Stack_make(size);
a->back = Stack_make(size);
a->size = size;
//initialize
Stack_push(a->front, DefaultValue);
for(i=0;i<size;++i){
Stack_push(a->back, DefaultValue);
}
a->index = 0;
return a;
}
void Array_pos_set(Array *a, size_t index){
if(index < 0 || index >= a->size){
fprintf(stderr, "out of range\n");
exit(-11);
}
if(a->index < index){
while(a->index < index){
Stack_push(a->front, Stack_pop(a->back));
++a->index;
}
} else if(a->index > index){
while(a->index > index){
Stack_push(a->back, Stack_pop(a->front));
--a->index;
}
}
}
Type Array_set(Array *a, size_t index, Type value){
Array_pos_set(a, index);//a->index == index
Stack_pop(a->front);
Stack_push(a->front, value);
return value;
}
Type Array_get(Array *a, size_t index){
Type value;
Array_pos_set(a, index);//a->index == index
value = Stack_pop(a->front);
Stack_push(a->front, value);
return value;
}
void Array_free(Array *a){
Stack_free(a->front);
Stack_free(a->back);
free(a);
}
int main(){
Array *a;
int i;
a = Array_make(10);
for(i=0;i<10;i++){
Array_set(a, i, i+1);//a[i] = i+1;
}
for(i=0;i<10;i++){
printf("%d\n", Array_get(a, i));// a[i];
}
Array_free(a);
return 0;
}
Related
I was given this code from Uni and I am trying to do operations with it , the push function ask for two pointers and I could not figure out how can I pass the data to the item part.I have tried using another structure containing the data but I failed. I am stuck at the end of the code and I would like to learn how to push data using this code. How can I proceed ?
It would be preferable if the data itself was stored in a structur.
Thanks in advance.
typedef struct stk
{
struct stk* elems[MAX]; int top;
} stack, *stackptr;
void Init(stack* s)
{
s->top = 0;
}
int IsEmpty(stack s)
{
return (s.top == 0);
}
void Push(struct stk* item, stack* s)
{
if (s->top == MAX)
printf("Stack voll!");
s->elems[s->top] = item;
s->top++;
}
struct stk* Pop(stack* s)
{
if (IsEmpty(*s)) return NULL;
s->top--;
return s->elems[s->top];
}
int main()
{
stack* ptr = (stackptr)malloc(sizeof(stack));
Init(ptr);
printf("%d\n", ptr->top); // Ist 0 , OK
}
Here is a working stack implementation that store ints. This will afford you the opportunity to test that the operations work as expected. If you really want to store stack * replace the type. It seems unnecessarily confusing for a entry level class to have an assignment of storing pointers to the same thing you are building.
When you deal with pointers you want to make sure the object they point to outline the pointer. You may also want to think of shallow and deep copies with pointers. If you Pop followed by a Push the pointer that was returned from Pop now will point to the new value which would be surprising. Consider a different designs:
Pass in a reference to a variable (aka out parameter) so Pop(stack *s, *v) (and use an enum or define constants for error values).
return a value instead of a pointer; error would not be an out parameter.
return a pointer to a copy of the value and require client to free it.
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
typedef struct stack {
int elems[MAX];
int top;
} stack;
void Init(stack *s) {
if(!s)
return;
s->top = 0;
}
int IsEmpty(stack *s) {
return (s->top == 0);
}
void Push(stack *s, int elem) {
if (s->top == MAX) {
printf("Stack voll!");
return;
}
s->elems[s->top++] = elem;
}
int *Pop(stack *s) {
if (IsEmpty(s))
return NULL;
return &s->elems[--(s->top)];
}
int main() {
stack *s = malloc(sizeof *s);
Init(s);
printf("%d\n", s->top); // Ist 0 , OK
Push(s, 42);
int *v = Pop(s);
printf("%d\n", *v);
}
and example run:
0
42
Consider using a name prefix like "Stack" for all your symbols to avoid name conflicts.
In c we don't cast void * (from malloc()).
I am new at C programming. I wrote some code for a stack exercise. The question is: one of the result is wrong, but when I debug step by step, the number changed abruptly. Could you help me solve this?
// #name mystack.c
// Created by lilei on 2017/3/10.
//
#include "mystack.h"
#include <malloc.h>
#include <stdio.h>
Stack createStack(){
Stack stack = (Stack)malloc(sizeof(Stack));
stack->top = -1;
return stack;
}
int isFull(Stack s){
if (s->top == MAXSIZE-1){
return 1;
} else{
return 0;
}
}
int push(Stack s, ElementType item){
if(!isFull(s)){
s->top++;
s->data[s->top] = item;
return 1;
} else{
printf("full!");
return 0;
}
}
int isEmpty (Stack s){
if(s->top == -1){
return 1;
} else{
return 0;
}
}
ElementType pop(Stack s){
if(!isEmpty(s)){
ElementType e = s->data[s->top];
s->top--;
return e;
}
}
void myPrintf(Stack s){
int len = s->top;
printf("The data are ");
while(len >= 0){
printf("%d ", s->data[len]);
len--;
}
printf("\n");
}
int main(){
Stack s = createStack();
for(int i = 0; i < 7; i++){
push(s, i*2);
}
myPrintf(s);
printf("isEmpty:%d, isFull:%d\n, pop one:%d", isEmpty(s), isFull(s), pop(s));
}
The result is
I can't see the declaration of Stack because you forgot to put it in th question, but it must be declared as a pointer to a struct e.g.
typedef struct
{
int top;
ElementType data[MAXSIZE];
} *Stack;
// ^- means pointer
So a Stack is a pointer type which means that, when you malloc it, you malloc only 4 or 8 bytes depending on whether you are compiling for 32 or 64 bit. The malloc line should be
Stack stack = malloc(sizeof *stack);
You were not allocating enough space on your stack for the actual stack structure which means that you are writing into bits of the heap you do not own and other things will write into the memory you think you have allocated for your stack.
There is another problem. What does your pop() function return if you try to pop something when the stack is empty? The answer is "could be anything". You either need to abort the program or return some error value.
I get a segfault while runnig this code to implement a stack in C. Please note that the code is kind of incomplete. I just wanted to check and see if I could push a few elements on to the stack and print them out. But it throws back a segfault. Any help would be much appreciated!!
#include<stdlib.h>
#include<stdio.h>
struct stack
{
int *elems;
int ll;
int al;
};
void stack_new(struct stack *s)
{
s->ll=0;
s->al=4;
s->elems=malloc(4*sizeof(int));
}
void stack_del(struct stack *s)
{
free(s->elems);
}
void stack_push(struct stack *s,int value)
{
if(s->ll==s->al)
{
printf("overflow");
/*s->al*=2;
s->elems=realloc(s->elems, s->al*sizeof(int));*/
}
s->elems[s->ll]=value;
s->ll++;
}
void stack_pop(struct stack *s)
{
s->ll--;
return (s->elems[s->ll]);
}
void main()
{
struct stack *s;
stack_new(s);
stack_push(s,3);
stack_push(s,4);
stack_push(s,8);
printf("%d", s->elems[0]);
//stack_pop(s);
//stack_del(s);
}
Declaring
struct stack *s;
doesn’t allocate any memory for a struct stack. Do that:
struct stack *s = malloc(sizeof *s);
Or just put your stack on the stack:
struct stack s;
stack_new(&s);
…
Using more descriptive field names is also a good idea.
You have several errors
You never initialize the pointer s in your main function, so in your stack_new function dereferencing s causes a segmentation fault.
You should allocate space for the stack first, wherever you want but you must.
Another thing is if you want to initialize your al field with a constant number and then allocate an array of constant size, you don't need the field al, and you can declare elems as int elems[CONSTANT_NUMBER] but if you want it to be dynamic, which is what I think you want from your check if(s->ll == s->al) in the stack_push function, then you can simply pass the value you want al to have to the stack_new function.
This is some of your code, fixed so you can see what I actually mean.
#include<stdlib.h>
#include<stdio.h>
struct stack
{
int *elems;
int ll;
int al;
};
struct stack *stack_new(int al) /* you can pass the maximum number of elements allowed */
{
struct stack *s;
s = malloc(sizeof(struct stack));
if (s == NULL)
return NULL;
s->ll = 0;
s->al = al;
s->elems = malloc(al * sizeof(int)); /* and you dynamically allocate space for them here */
return s;
}
void stack_del(struct stack *s)
{
if (s != NULL) /* always check the pointers to prevent `SEGMENTATION FAULT` */
{
if (s->elems != NULL)
free(s->elems);
free(s);
}
}
void stack_push(struct stack *s, int value)
{
if (s == NULL)
return;
if(s->ll == s->al)
{
printf("overflow");
/*s->al*=2;
s->elems=realloc(s->elems, s->al*sizeof(int));*/
}
if (s->elems != NULL)
s->elems[s->ll] = value;
s->ll++;
}
int stack_pop(struct stack *s)
{
if ((s == NULL) || (s->elems == NULL))
return 0;
s->ll--;
return (s->elems[s->ll]);
}
int main()
{
struct stack *s;
s = stack_new(4);
stack_push(s, 3);
stack_push(s, 4);
stack_push(s, 8);
printf("%d", s->elems[0]);
stack_pop(s);
stack_del(s);
return 0;
}
```
I tried implementing Dynamic array in C, where size is doubled every time stack is found to be full. When I try to push more than 8 elements, it fails. Output it gave was:
stack empty (since nothing is pushed on to it yet)
|1|
yes (indicates: double operation called)
|2|
yes
|3|
|4|
yes
|5|
|6|
|7|
|8|
yes
Can anyone explain why does it work only for size of stack up to 8 (n<=8, in main)
Thanks
code:
#include
#include
struct stkarr{ //structure for a node
int top;
int capacity;
int *arr;
};
struct stkarr* buildstk(){ //build an object stack (s)
struct stkarr *s = (struct stkarr*)malloc(sizeof(struct stkarr));
// since it's a dynamic array we start with capacity = 1
s->capacity=1;
s->top=-1;
s->arr = (int*)malloc(s->capacity*sizeof(int));
return s;
};
int is_stk_full(struct stkarr* s){
return(s->top==s->capacity-1); // 1->yes, 0->no
}
int is_stk_empty(struct stkarr* s){
return(s->top==-1);
}
void dbl_stk(struct stkarr *s){//doubling the size of stack
(s->capacity)*=2;
s->arr = realloc(s->arr,s->capacity);
}
void psh(struct stkarr* s,int val){ //push
if(is_stk_full(s)){
printf("yes\n");
dbl_stk(s);
}
s->arr[++s->top] = val;
}
int pop(struct stkarr* s){
if(is_stk_empty(s)){
printf("stack empty\n");
return;
}
else{
return s->arr[s->top--];
}
}
int main(){
struct stkarr* s;
int i,n;
n=10;
s = buildstk();
//checking empty stack exception
pop(s);
for(i=0;i<n;i++){
//push operation
psh(s,i+1);
printf("|%d|\n",pop(s)); // just checking if i+1 is pushed or not
psh(s,i+1); // since I popped i+1, pushing it again on to stack
}
//never reaches here for n>8
for(i=0;i<n;i++){//popping elements and printing them
//pop operation
printf("|%d|\n",pop(s));
}
return 0;
}
Your buffer isn't big enough. realloc(s->arr,s->capacity); should be realloc(s->arr,s->capacity * sizeof(int));
// Whenever i am increasing function call times of push more than 8, it get crashed before that everything is working good. your help is required. In the below code i have created a program for stack using Dynamic array keeping in mind there should not be any stack overflow by using realloc function to doubling the values whenever the stack gets filled.
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
typedef struct ArrayStack
{
int top;
int capacity;
int *arr;
}*stack;
stack Creation()
{
stack S;
S=(stack)malloc(sizeof(struct ArrayStack));
if(!S)return NULL;
S->top=-1;
S->capacity=1;
S->arr=(int*)malloc(S->capacity*sizeof(int));
if(!S->arr)return NULL;
return S;
}
int is_Full(stack S)
{
return S->top==S->capacity-1;
}
int is_Empty(stack S)
{
return S->top==-1;
}
void Doubling(stack S)
{
S->capacity*=2;
S->arr=realloc(S->arr,S->capacity);
}
void push(stack S,int data)
{
if(is_Full(S))
Doubling(S);
S->arr[++S->top]=data;
}
int pop(stack S)
{
if(is_Empty(S))
printf("\nStack underflow");
else
return S->arr[S->top--];
}
int main()
{
stack S;
int i=0,size=9;
S=Creation();
**for(i=0;i<size;i++)
push(S,19+1);** // As in this case
return 0;
}
S->arr = malloc(S->capacity * sizeof(int));
S->arr = realloc(S->arr, S->capacity);
You only reallocate enough space for S->capacity / sizeof(int) items.