Theo Van Dinter, 96/04/10, Algorithms Homework #6
Also available via http://www.kluge.net/~felicity/proj/cs2223-hw6.html

1) What value is returned by the following program when invoked by P(n)? You may assume that the input value n is a power of 2. Your answer should be expressed as a simple (not recursive) function of n.

int P(int n)
{
	int i,j,sum;
	if (n==1) return 1;
	sum=P(n/2);
	for (i=0;i<n;i++)
		for (j=0;j<n;j++) sum++;
	sum+=P(n/2);
	return sum;
}
Theo's Answer:

ntotalbreakdown of total
111
261+4+1
4281+4+1+16+1+4+1
81201+4+1+16+1+4+1+64+1+4+1+16+1+4+1

I looked at the breakdown, and I noticed a pattern... The middle term is always n2. There is also (when n>1) n number of +1 terms. For n=4, there is n2+n+n+n (4+4+4*1). For n=2, there's n2+n. n=8 provides n2+7*n (4+4+4+4=2n, 8*1=1n, 2*16=4n, sum=7n.)

From this, if another n is added, the sum is 2*n2. Then just remove the n that was added for the actual sum. Therefore the answer is:

2n2-n

2) A divide-&-conquer implementation of a priority queue is a binary search tree (see, for example, Section 5.5 of our text). Test this data structure by writing and testing a program to do the following:

Describe your implementation, and estimate the time to perform an insert and a delete-min (as a function of n) for your implementation. As a check that your program is performing correctly, you should note that constructing a new priority queue, then performing n inserts followed by n delete-mins returns the input in sorted order.

The best and average time to insert an element into a binary search tree with n-elements is O(lgn) because adding an element requires you to go completely through a branch of the tree with height lgn (for best case, approximately that (+/- a small constant for large n) for average case.) Worst case is in O(n) time due to the height of the branch the program goes through being n.

The implementation for insert is as follows:

For delete-min, the best and average cases are also O(lgn) because to get to the minimum value, only the left children must be traversed, and then the actual deletion is completed in constant time. Worst time is O(n).

The implementation for delete-min is:

Summary:

functionbest/average casesworst case
delete-min()Theta(lgn)Theta(n)
insert()Theta(lgn)Theta(n)


Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <malloc.h>

typedef struct btn {
  int value;
  struct btn *root,*left,*right;
} BTNode;

BTNode *root=NULL;

void insert(int);
void insertnode(BTNode *,BTNode *,int,int);
void printtree(BTNode *);
void deltree(void);
void deletetree(BTNode *);
void delmin(void);
BTNode *delminimum(BTNode *);

void main()
{
  int n,loo,temp,max,m;
  int array[]={100000,200000,400000,800000,0};
  clock_t start,finish,end1;

  srand(time(NULL)^((getpid()<<15)+3*getpid()+1));

  m=array[0]/5;
  temp=0;
  while(array[temp]!=0)
    {
      n=array[temp];
      printf("Now doing %d ...\n",n);
      for(loo=0;loo<n;loo++)
          insert(rand());
      start=clock();
      for(loo=0;loo<m;loo++)
        insert(rand());
      end1=clock();
      for(loo=0;loo<n;loo++)
          delmin();
      finish=clock();
      deltree();
      temp++;
      printf("Insertion of %d took %.9f\n%d deletions took %.9f.\n\n",m,((double)(end1-start)/((double)(CLOCKS_PER_SEC))),m,((double)(finish-end1)/((double)(CLOCKS_PER_SEC))));
      sleep(1);
    }
  return;
}

void delmin(void)
{
  BTNode *temp;
  if (root==NULL)
    return;
  if (root->left==NULL)
    {
      temp=root->right;
      free(root);
      root=temp;
      if ( root!=NULL )
        root->root=NULL;
      return;
    }
  temp=root->left;
  while(temp!=NULL)
    temp=delminimum(temp);
  return;
}


BTNode *delminimum(BTNode *r)
{
  BTNode *rr;
  if (r->left==NULL)
    {
      if (r->right==NULL)
        {
          rr=r->root;
          free(r);
          rr->left=NULL;
          return NULL;
        }
      rr=r->root;
      rr->left=r->right;
      free(r);
      rr->left->root=rr;
      return NULL;
    }
  return r->left;
}

void printtree(BTNode *r)
{
  if (r==NULL)
    return;
  if ( r->left!=NULL )
    printtree(r->left);
  printf("%d\n",r->value);
  if ( r->right!=NULL )
    printtree(r->right);
  return;
}

void deltree(void)
{
  deletetree(root);
  root=NULL;
  return;
}

void deletetree(BTNode *r)
{
  if (r==NULL)
    return;
  if ( r->left!=NULL )
    deletetree(r->left);
  if ( r->right!=NULL )
    deletetree(r->right);
  free(r);
  return;
}

void insert(int x)
{
  if ( root==NULL )
    {
      root=(BTNode *)malloc(sizeof(BTNode));
      root->root=NULL;
      root->left=NULL;
      root->right=NULL;
      root->value=x;
      return;
    }
  insertnode(root,root->root,x,0);
  return;
}

void insertnode(BTNode *r, BTNode *rr, int x, int side)
{
  int temp;
  if ( r==NULL )
    {
      r=(BTNode *)malloc(sizeof(BTNode));
      if ( side )
        rr->right=r;
      else rr->left=r;
      r->left=NULL;
      r->right=NULL;
      r->value=x;
      r->root=rr;
      return;
    }

  if ( x<r->value )
    {
      insertnode(r->left,r,x,0);
      return;
    }
  else if (x>r->value)
    {
      insertnode(r->right,r,x,1);
      return;
    }

  /* x=r, now what? */

  if ( r->left!=NULL && r->right==NULL )
    {
      insertnode(r->right,r,x,1);
      return;
    }
  else if (r->left==NULL && r->right!=NULL )
    {
      insertnode(r->left,r,x,0);
      return;
    }

  /* either both right + left are defined, or none are ... */

  temp=rand()%2;
  insertnode(temp?r->right:r->left,r,x,temp);
  return;
}