Unit DeqUnit;

Interface

Type
  TData = Char;
  PTDeqItem = ^TDeqItem;
  TDeqItem =
    Record
      Data: TData;
      next, prev: PTDeqItem;
    End;

  TDeq =
    Record
      pStart, pFinish: PTDeqItem;
    End;

Function isEmpty(Var Deq: TDeq): Boolean;

Procedure PrintDeck(Var Deq: TDeq);

Procedure PushStart(Var Deq: TDeq; Ch: TData);
Procedure PushFinish(Var Deq: TDeq; Ch: TData);
Function PopStart(Var Deq: TDeq): TData;
Function PopFinish(Var Deq: TDeq): TData;

Procedure InitDeq(Var Deq: TDeq);
Procedure DestroyDeq(Var Deq: TDeq);

Implementation

Function isEmpty(Var Deq: TDeq): Boolean;
  Begin
    isEmpty := (Deq.pStart = nil);
  End;

Procedure PrintDeck(Var Deq: TDeq);
  Var p: PTDeqItem;
  Begin
    WriteLn( 'Printing Deck...' );
    If isEmpty(Deq) Then
      Begin
        WriteLn('<empty>'); Exit
      End;

    p := Deq.pStart;
    While p <> nil Do
      Begin
        Write( p^.Data, ' ' );
        p := p^.next
      End;
    WriteLn
  End;
Procedure PushStart(Var Deq: TDeq; Ch: TData);
  Var newItem: PTDeqItem;
  Begin
    newItem := new(PTDeqItem);
    newItem^.next := Deq.pStart;
    newItem^.prev := nil;
    newItem^.Data := Ch;

    If Deq.pStart <> nil Then
      Deq.pStart^.prev := newItem
    Else
      Deq.pFinish := newItem;

    Deq.pStart := newItem;
  End;

Procedure PushFinish(Var Deq: TDeq; Ch: TData);
  Var newItem: PTDeqItem;
  Begin
    newItem := new(PTDeqItem);
    newItem^.next := nil;
    newItem^.prev := Deq.pFinish;
    newItem^.Data := Ch;

    If Deq.pFinish <> nil Then
      Deq.pFinish^.next := newItem
    Else
      Deq.pStart := newItem;

    Deq.pFinish := newItem;
  End;

Function PopStart(Var Deq: TDeq): TData;
  Var ToDelete: PTDeqItem;
  Begin
    PopStart := #0;
    If isEmpty(Deq) Then Exit;

    ToDelete := Deq.pStart;
    Deq.pStart := ToDelete^.next;

    If Deq.pStart <> nil Then
      Deq.pStart^.prev := nil
    Else
      Deq.pFinish := nil;

    PopStart := ToDelete^.Data;
    Dispose(ToDelete);
  End;

Function PopFinish(Var Deq: TDeq): TData;
  Var ToDelete: PTDeqItem;
  Begin
    PopFinish := #0;
    If isEmpty(Deq) Then Exit;

    ToDelete := Deq.pFinish;
    Deq.pFinish := ToDelete^.prev;

    If Deq.pFinish <> nil Then
      Deq.pFinish^.next := nil
    Else
      Deq.pStart := nil;

    PopFinish := ToDelete^.Data;
    Dispose(ToDelete);
  End;


Procedure InitDeq(Var Deq: TDeq);
  Begin
    Deq.pStart := nil;
    Deq.pFinish := nil;
  End;

Procedure DestroyDeq(Var Deq: TDeq);
  Begin
    While not isEmpty(Deq) Do PopStart(Deq);
  End;

Begin
End.