next up previous
Next: About this document Up: My Home Page

List Insertion and Deletion
Lecture 7

Steven S. Skiena

Search, Insert, Delete

There are three fundamental operations we need for any database:

We will see a wide variety of different implementation of these operations over the course of the semester.

How would you implement these using an array?

With linked lists, we can creating arbitrarily large structures, and never have to move any items.

Most of these operations should be pretty simple now that you understand pointers!

Searching in a Linked List

Procedure Search(head:pointer, key:item):pointer;
Var
   p:pointer;
   found:boolean;
Begin
   found:=false;
   p:=head;
   While (p # NIL) AND (not found) Do
    Begin
       If (p^.info = key) then 
          found = true;
       Else
          p = p^.next;
   End;
   return p;
END;

Search performs better when the item is near the front of the list than the back.

What happens when the item isn't found?

Insertion into a Linked List

The easiest way to insert a new node p into a linked list is to insert it at the front of the list:

p^.next = front;
front = p;

To maintain lists in sorted order, however, we will want to insert a node between the two appropriate nodes. This means that as we traverse the list we must keep pointers to both the current node and the previous node.

MODULE Intlist;                      (*16.07.94. RM, LB*)
(* Implementation of sorted integer lists. *)
 
  REVEAL                             (*reveal inner structure of T*)
    T = BRANDED REF RECORD
          key: INTEGER;              (*key value*)
          next: T := NIL;            (*pointer to next element*)
        END; (*T*)
 
  PROCEDURE Create(): T =
  (* returns a new, empty list *)
  BEGIN
    RETURN NIL;  (*creation is trivial; empty list is NIL*)
  END Create;
 
  PROCEDURE Insert(VAR list: T; value:INTEGER) =
  (* inserts new element in list and maintains order *)
  VAR 
    current, previous: T;
    new: T := NEW(T, key:= value);   (*create new element*)
  BEGIN
    IF list = NIL THEN list:= new    (*first element*)
    ELSIF value < list.key THEN      (*insert at beginning*)
      new.next:= list; list:= new;
    ELSE                             (*find position for insertion*)
      current:= list; 
      previous:= current;
      WHILE (current # NIL) AND (current.key <= value) DO
        previous:= current;          (*previous hobbles after*)
        current:= current.next; 
      END;  
      (*after the loop previous points to the insertion point*)
      new.next:= current;
           (*current = NIL if insertion point is the end*)
      previous.next:= new;           (*insert new element*)
    END; (*IF list = NIL*)
  END Insert;

Make sure you understand where these cases come from and can verify why all of them work correct.

Deletion of a Node

To delete a node from a singly linked-list, we must have pointers to both the node-to-die and the previous node, so we can reconnect the rest of the list.

  PROCEDURE Remove(VAR list: T; value:INTEGER; VAR found: BOOLEAN) =
  (* deletes  (first) element with value from sorted list,
     or returns false in found if the element was not found *) 
  VAR 
    current, previous: T;
  BEGIN
    IF list = NIL THEN found:= FALSE
    ELSE                             (*start search*)
      current:= list; previous:= current;
      WHILE (current # NIL) AND (current.key # value) DO
        previous:= current;          (*previous hobbles after*)
        current:= current.next;
      END;  
      (*holds: current = NIL or current.key = value, but not both*)
      IF current = NIL THEN 
        found:= FALSE                (*value not found*)
      ELSE
        found:= TRUE;                (*value found*)
        IF current = list THEN 
          list:= current.next        (*element found at beginning*)
        ELSE 
          previous.next:= current.next
        END;
      END; (*IF current = NIL*)
    END; (*IF list = NIL*)
  END Remove;

Passing Procedures as Arguments

Note the passing of a procedure as a parameter - it is legal, and useful to make more general functions, for example a sort routine for both increasing and decreasing order, or any order.

 
  PROCEDURE Iterate(list: T; action: Action) =
  (* applies action to all elements (with key value as parameter) *)
  BEGIN
    WHILE list # NIL DO
      action(list.key); 
      list:= list.next;
    END;
  END Iterate;
 
BEGIN  (* Intlist *)
END Intlist.

Pointers and Parameter Passing

Pointers provide, for better or (usually) worse, and alternate way to modify parameters. Let us look at two different ways to swap the ``values'' of two pointers.

Procedure Swap1(var p,q:pointer);
Var r:pointer;
begin
     r:=q;
     q:=p;
     p:=r;
end;

This is perhaps the simplest and best way - we just exchange the values of the pointers...

Alternatively, we could swap the values of what is pointed to, and leave the pointers unchanged.

Procedure Swap2(p,q : pointer);
var tmp : node;
begin
     tmp := q^;  (*1*)
     q^ := p^;   (*2*)
     p^ := tmp;  (*3*)
end;

After step (*1*):

After step (*2*):

After step (*3*):

Side Effects of Pointers

If swap2, since we do not change the values of p and q, they do not need to be var parameters!

However, copying the values did not do the same thing as copying the pointers, because in the first case the physical location of the data changed, while in the second the data stayed put.

If data which is pointed to moves, the value of what is pointed to can change!

Moral: you must be careful about the side effects of pointer operations!!!

C language does not have var parameters. All side effects are done by passing pointers. Additional pointer operations in C language help make this practical.




next up previous
Next: About this document Up: My Home Page

Steve Skiena
Tue Sep 23 15:55:39 EDT 1997