I've tried to make a DEQUE program. My book on data structures (Seymour Lipschutz) doesn't have an algorithm on DEQUES. Neither does DADS give a good description.
All I heard was that it could be implemented better with two lists (one forward and one backward) & there are 2 types of DEQUES (INPUT & OUTPUT restricted). But the program has become too long. So I was wondering if the code can be made shorter.
Please offer your (constructive) criticisms
#include <stdio.h>
#include <malloc.h>
/*
*===========================================================
* PROGRAM DESCRIPTION - IMPLEMENTATION OF A DEQUE |
* AUTHOR - SUMITRO BHAUMIK AKA "XAVIER666" |
* DATE - 11TH DECEMBER, 2009 |
* COMPILER - CODE::BLOCKS 8.02 |
* OS - WINDOWS XP SP2 |
*===========================================================
*
* NOTES - I THINK THE RESTRICTION CODES (RC) NEEDS TO BE EXPLAINED
* SINCE DEQUES CAN BE EITHER INPUT OR OUTPUT RESTRICTED,
* ALL I DID WAS JUST NOT LET THE FUNCTION BE ACCESSSED.
* THE RCs ARE CLOSELY LINKED WITH THESE (LINE 120) SWITCH CASE VALUES
* IF THE USER WANTS INPUT TOP RESTRICTED, RC = 1
* DURING THE DEQUE OPERATIONS MENU, IF THE RC IS SAME AS SWITCH CASE VALUE,
* THAT OPTION IS RESTRICTED. THE OTHER RC CODES OPERATE THE SAME WAY
*/
typedef struct deque
{
int data;
struct deque *forward;
struct deque *backward;
}node;
void push_top( int ); // SAME AS PUSHING IN STACK
void push_end( int ); // SAME AS PUSHING IN QUEUE
void pop_top( void ); // POPPING THE ELEMENTS FROM THE TOP OF DEQUE
void pop_end( void ); // POPPING THE ELEMENTS FROM THE BOTTOM OF DEQUE
void show_forward( void ); // DISPLAY OF DEQUE : TOP TO BOTTOM
void show_backward( void ); // DISPLAY OF DEQUE : BOTTOM TO TOP
int length_deque( void ); // PRINTS LENGTH OF DEQUE
void print_warning( void ); // PRINTS A RESTRICTION VIOLATION WARNING
void pause( FILE * ); // PAUSES THE PROGRAM DURING RUNTIME FOR READABILITY
int main()
{
int element; // STORES THE DATA (AN INTEGER NUMBER) FROM USER
int option; // STORES OPTIONS FROM USER
int fl; // A FLAG VARIABLE
int restriction_code; // ITS VALUE DENOTES THE TYPE OF RESTRICTION IMPOSED
// ON THE DEQUE
fl = 0;
// THIS DO-WHILE LOOP FOR THE 'DEQUE OPERATIONS' MENU
do
{
// THIS MENU WILL NOT ALWAYS RUN EXCEPT WHEN NEEDED,
if (fl == 0) // <- HENCE THIS FLAG VARIABLE
{
// THIS DO-WHILE FOR THE 'TYPE OF DEQUE' MENU
do
{
printf("\n\n\tWhat Type Of DEQUE Would You Like?");
printf("\n\n\t\tINPUT Restricted ..... [1]");
printf("\n\n\t\tOUTPUT Restricted .... [2]");
printf("\n\n\t\tNon Restricted ....... [3]");
printf("\n\n\tEnter Your Option : ");
scanf("%d", &option);
switch(option)
{
case 1 :
restriction_code = 0;
printf("\n\n\tINPUT Restrictrion Type");
printf("\n\n\t\tTop Restricted ....... [1]");
printf("\n\n\t\tBottom Restricted .... [2]");
printf("\n\n\tEnter Your Option : ");
scanf("%d", &option);
pause(stdin);
restriction_code += option;
break;
case 2 :
restriction_code = 2;
printf("\n\n\tOUTPUT Restrictrion Type");
printf("\n\n\t\tTop Restricted ....... [1]");
printf("\n\n\t\tBottom Restricted .... [2]");
printf("\n\n\tEnter Your Option : ");
scanf("%d", &option);
pause(stdin);
restriction_code += option;
break;
case 3 :
break;
default:
printf("\n\n\tChoice Does Not Exist");
pause(stdin);
break;
}
}while(option > 3 || option < 1);
// THE TYPE OF DEQUE HAS BEEN DECIDED
fl = 1; // HENCE, WILL NOT RUN AGAIN EXCEPT WHEN NEEDED
}
printf("\n\t==================================\n");
printf("\t| DEQUE OPERATIONS |");
printf("\n\t==================================\n");
printf("\n\n\tPush Element From Top ........ [1]");
printf("\n\n\tPush Element From End ........ [2]");
printf("\n\n\tPop Element From Top ......... [3]");
printf("\n\n\tPop Element From End ......... [4]");
printf("\n\n\tShow DEQUE From Front ........ [5]");
printf("\n\n\tShow DEQUE From End .......... [6]");
printf("\n\n\tShow Length Of DEQUE ......... [7]");
printf("\n\n\tGo Back To DEQUE TYPE ........ [8]");
printf("\n\n\tExit Program ................. [0]");
printf("\n\n\tEnter Your Option : ");
scanf("%d", &option);
switch(option)
{
case 1 :
if(option == restriction_code)
{
print_warning();
pause(stdin);
break;
}
printf("\n\n\tEnter The Element : ");
scanf("%d",&element);
push_top(element);
pause(stdin);
break;
case 2 :
if(option == restriction_code)
{
print_warning();
pause(stdin);
break;
}
printf("\n\n\tEnter The Element : ");
scanf("%d",&element);
push_end(element);
pause(stdin);
break;
case 3 :
if(option == restriction_code)
{
print_warning();
pause(stdin);
break;
}
pop_top();
pause(stdin);
break;
case 4 :
if(option == restriction_code)
{
print_warning();
pause(stdin);
break;
}
pop_end();
pause(stdin);
break;
case 5 :
show_forward();
pause(stdin);
break;
case 6 :
show_backward();
pause(stdin);
break;
case 7 :
printf("\n\n\tLength Of DEQUE : %d", length_deque());
pause(stdin);
break;
case 8 :
fl = 0;
break;
case 0 :
printf("\n\n\tThank You ... ");
break;
default:
printf("\n\n\tChoice Does Not Exist!");
pause(stdin);
break;
}
}while(option != 0);
return 0;
}
node *head; // STORES ADRESS OF STARTING ELEMENT
node *tail; // STORES ADRESS OF ENDING ELEMENT
node *temp1; // CONTROL VARIABLE FOR ALL FORWARD TRAVERSAL RELATED TASK
node *temp2; // CONTROL VARIABLE FOR ALL BACKWARD TRAVERSAL RELATED TASK
node *temp3; // STORES NEWLY GENERATED ADDRESS FOR FORWARD QUEUE
node *temp4; // STORES NEWLY GENERATED ADDRESS FOR BACKWARD QUEUE
int length; // STORES LENGTH OF DEQUE
int popped; // STORES THE POPPED ELEMENT
void push_top( int n )
{
temp1 = head;
temp2 = tail;
if(temp1 == NULL) // EMPTY DEQUE
{
// 1ST TIME CREATING HEAD
temp1 = (node *)malloc(sizeof(node));
temp1 -> data = n;
temp1 -> forward = NULL;
head = temp1;
// 1ST TIME CREATING TAIL
temp2 = (node *)malloc(sizeof(node));
temp2 -> data = n;
temp2 -> backward = NULL;
tail = temp2;
}
else
{
// ADDING NEW ELEMENT & MAKING IT THE NEW HEAD
temp3 = (node *)malloc(sizeof(node));
temp3 -> data = n;
temp3 -> forward = head;
head = temp3;
// GOING TO 2ND LAST ELEMENT OF BACKWARD LIST
while(temp2 -> backward != NULL)
temp2 = temp2 -> backward;
// ADDING NEW ELEMENT & MAKING IT POINT TO NULL
temp4 = (node *)malloc(sizeof(node));
temp4 -> data = n;
temp4 -> backward = NULL;
// POINTING THE 2ND LAST ELEMENT TO THE NEW LAST ELEMENT
temp2 -> backward = temp4;
}
length ++;
}
void push_end( int n )
{
temp1 = head;
temp2 = tail;
if(temp2 == NULL) // EMPTY DEQUE
{
// 1ST TIME CREATING TAIL
temp2 = (node *)malloc(sizeof(node));
temp2 -> data = n;
temp2 -> backward = NULL;
tail = temp2;
// 1ST TIME CREATING HEAD
temp1 = (node *)malloc(sizeof(node));
temp1 -> data = n;
temp1 -> forward = NULL;
head = temp1;
}
else
{
// ADDING NEW ELEMENT & MAKING IT TAIL
temp4 = (node *)malloc(sizeof(node));
temp4 -> data = n;
temp4 -> backward = tail;
tail = temp4;
// GOING TO 2ND LAST ELEMENT OF FORWARD LIST
while(temp1 -> forward != NULL)
temp1 = temp1 -> forward;
// ADDING NEW ELEMENT & MAKING IT POINT TO NULL
temp3 = (node *)malloc(sizeof(node));
temp3 -> data = n;
temp3 -> forward = NULL;
// POINTING THE 2ND LAST ELEMENT TO THE NEW LAST ELEMENT
temp1 -> forward = temp3;
}
length ++;
}
void pop_top()
{
temp1 = head;
temp2 = tail;
if(temp1 == NULL) // EMPTY DEQUE
{
printf("\n\n\tDEQUE Empty!\n\tQUEUE UNDERFLOW\n");
return;
}
else if(temp1 -> forward == NULL) // IF THERE IS ONLY ONE ELEMENT,
{ // THE 3RD 'ELSE' BLOCK WON'T WORK
popped = temp1 -> data; // HENCE, THIS 'ELSE IF' BLOCK
free(temp1);
head = NULL;
free(temp2);
tail = NULL;
return;
}
else
{
// GOING TO 2ND ELEMENT OF FORWARD LIST
temp3 = temp1 -> forward;
popped = temp1 -> data;
free(temp1);
// MAKING THE 2ND ELEMENT THE NEW HEAD
head = temp3;
// GOING TO 2ND LAST ELEMENT OF BACKWARD LIST
while(temp2 -> backward -> backward != NULL)
temp2 = temp2 -> backward;
// RELEASING THE LAST ELEMENT
free(temp2 -> backward);
// POINTING THE 2ND LAST ELEMENT TO NULL
temp2 -> backward = NULL;
}
printf("\n\n\tPopped Element : %d", popped);
length --;
}
void pop_end()
{
temp1 = head;
temp2 = tail;
if(temp2 == NULL) // EMPTY DEQUE
{
printf("\n\n\tDEQUE Empty!\n\tQUEUE UNDERFLOW\n");
return;
}
else if(temp2 -> backward == NULL) // IF THERE IS ONLY ONE ELEMENT,
{ // THE 3RD 'ELSE' BLOCK WON'T WORK
popped = temp2 -> data; // HENCE, THIS 'ELSE IF' BLOCK
free(temp2);
tail = NULL;
free(temp1);
head = NULL;
}
else
{
// GOING TO 2ND ELEMENT OF BACKWARD LIST
temp4 = temp2 -> backward;
popped = temp2 -> data;
free(temp2);
// MAKING THE 2ND ELEMENT THE NEW HEAD
tail = temp4;
// GOING TO 2ND LAST ELEMENT OF FORWARD LIST
while(temp1 -> forward -> forward != NULL)
temp1 = temp1 -> forward;
// RELEASING THE LAST ELEMENT
free(temp1 -> forward);
// POINTING THE 2ND LAST ELEMENT TO NULL
temp1 -> forward = NULL;
}
printf("\n\n\tPopped Element : %d", popped);
length --;
}
void show_forward()
{
temp1 = head;
if(temp1 == NULL) // EMPTY DEQUE
{
printf("\n\n\tEMPTY DEQUE!");
return;
}
printf("\n\n\tThe DEQUE :- ");
while(temp1 != NULL)
{
printf("\n\t%d",temp1 -> data);
temp1 = temp1 -> forward;
}
}
void show_backward()
{
temp2 = tail;
if(temp2 == NULL) // EMPTY DEQUE
{
printf("\n\n\tEMPTY DEQUE!");
return;
}
printf("\n\n\tThe DEQUE :- ");
while(temp2 != NULL)
{
printf("\n\t%d",temp2 -> data);
temp2 = temp2 -> backward;
}
}
int length_deque()
{
return length;
}
void print_warning()
{
printf("\n\n\tSorry! Restrictions Are Imposed On This Option");
printf("\n\n\tTry The Other Options Or Lift The Restrictions");
}
void pause(FILE *in)
{
printf("\n\n\tPress Enter To Continue ... ");
if(!feof(in) && !ferror(in))
{
int ch;
do
{
ch = getc(in);
}while ( ch != '\n' && ch != EOF );
clearerr(in);
}
getchar();
}