(i) Code for inserting and removing elements at the start and end of a doubly and circular linked list. 

(ii) Using templates, write code to push and pop elements, check Isempty and Isfull, and return the top element in stacks.

Algorithm/Flowchart (For programming based labs):
Circular LinkList
insertFirst(data):
Begin
 create a new node
 node -> data := data
 if the list is empty, then
 head := node
 next of node = head
 else
 temp := head
 while next of temp is not head, do
 temp := next of temp
 done
 next of node := head
 next of temp := node
 head := node
 end if
end
deleteFirst():
Begin
 if head is null, then
 it is Underflow and return
 else if next of head = head, then
 head := null
 deallocate head
 else
 ptr := head
 while next of ptr is not head, do
 ptr := next of ptr
 next of ptr = next of head
 deallocate head
 head := next of ptr
 end if
Stack Algorithm.
Push(data):
begin
if stack is full
 return
endif
else
increment top
stack[top] assign value
end else
end procedure
POP():
begin
if stack is empty
 return
endif
else
store value of stack[top]
decrement top
return value
end else
end procedure
Top():
begin
 return stack[top]
end procedure


#include <iostream>
#include <stdlib.h>
using namespace std;
struct node
{
    int data;
    struct node *next;
};
// insertion in link list at frist index
struct node *insertAtFrisrt(struct node *head, int data)
{
    struct node *ptr = (struct node *)malloc(sizeof(struct node));
    ptr->data = data;
    struct node *p = head->next;
    while (p->next != head)
    {
        p = p->next;
    }
    p->next = ptr;
    ptr->next = head;
    head = ptr;
    return head;
}
void display(struct node *head)
{
    struct node *ptr = head;
    do
    {
        cout << "The element of Linklist is: " << ptr->data << endl;
        ptr = ptr->next;
    } while (ptr != head);
}
using namespace std;
int main()
{
    struct node *head = (struct node *)malloc(sizeof(struct node));
    struct node *second = (struct node *)malloc(sizeof(struct node));
    struct node *third = (struct node *)malloc(sizeof(struct node));
    struct node *fourth = (struct node *)malloc(sizeof(struct node));
    struct node *fivth = (struct node *)malloc(sizeof(struct node));
    head->data = 11;
    head->next = second;
    second->data = 12;
    second->next = third;
    third->data = 13;
    third->next = fourth;
    fourth->data = 14;
    fourth->next = fivth;
    fivth->data = 15;
    fivth->next = head;
    display(head);
    cout << "Insertion at frist\n";
    head = insertAtFrisrt(head, 10);
    display(head);
    return 0;
}


2.
#include <iostream>
#include <stdlib.h>
using namespace std;
struct stack
{
    int size;
    int top;
    int *arr;
};
int isFull(struct stack *ptr)
{
    if (ptr->top == ptr->size - 1)
    {
        return 1;
    }
    return 0;
}
int isEmpty(struct stack *ptr)
{
    if (ptr->top == -1)
    {
        return 1;
    }
    return 0;
}
void push(struct stack *ptr, int value)
{
    if (isFull(ptr))
    {
        cout << "Stack is overflow" << endl;
    }
    else
    {
        ptr->top++;
        ptr->arr[ptr->top] = value;
    }
}
void pop(struct stack *ptr)
{
    if (isEmpty(ptr))
    {
        cout << "stack is Underflow" << endl;
    }
    else
    {
        int val = ptr->arr[ptr->top];
        ptr->top--;
    }
}
void traversal(struct stack *ptr)
{
    for (int i = ptr->top; i >= 0; i--)
    {
        cout << "the element of stack is -> " << ptr -
            > arr[i] << endl;
    }
}
int main()
{
    struct stack *sp = (struct stack *)malloc(sizeof(struct
                                                     stack));
    sp->size = 10;
    sp->top = -1;
    sp->arr = (int *)malloc(sp->size * sizeof(int));
    push(sp, 10);
    push(sp, 11);
    push(sp, 12);
    push(sp, 13);
    push(sp, 14);
    push(sp, 15);
    push(sp, 16);
    push(sp, 17);
    pop(sp);
    pop(sp);
    traversal(sp);
    return 0;
}