(PDF) Fundamentals of Data Structure in C
(PDF) Fundamentals of Data Structure in C
Data Structure in C
Ellis Horowitz
University of southern California
Chapter 1. BASIC CONCEPT
〖example1〗selection sort
algorithm:
for (i=0; i<n; i++) {
examine list[i] to list[n-1] and suppose that the
smallest integer is at list[min];
interchange list[i] and list[min];
}
Program:
for interchanging:
1. macro version
#define swap (x, y, t ) (( t ) = ( x ), ( x ) = ( y ), ( y ) = ( t ))
2. function version swap ( int *a, *b);
void swap ( int *x, int *y ) /* both parameters are pointers
to ints */
{ int temp = *x ; /* declares temp as an int and assigns
to it the contents of what x points to */
*x = *y; /* stores what y points to into the location
where x points*/
*y = temp; /*places the contents of temp in location
pointed to by y*/
}
#include<stdio.h>
#include<math.h>
#define MAX_SIZE 101
#define SWAP(x, y, t) ((t) = (x),(x) = (y), (y) = (t))
void sort ( int [ ], int ); /*selection sort*/
void main (void)
{
int i,n;
int list [MAX_SIZE];
printf ("Enter the number of numbers to generate; ");
scan ("%d", &n);
if ( n < 1 || n > MAX_SIZE) {
printf (stderr, "Improper value of n\n");
exit (1);
}
for (i = 0; i < n; i++) { /* randomly generate numbers*/
list [ i ] = rand ( ) % 1000;
printf ("%d ",list [ i ]);
}
sort ( list , n ) ;
printf ( " \n Sorted array: \n ");
for ( i = 0 ; i < n ; i++ ) /*print out sorted numbers */
printf ( "%d ", list [ i ] );
printf ( " \n " );
}
void sort ( int list [ ] ,int n )
{
int i, j, min, temp;
for ( i = 0; i < n-1; i++ ) {
min = i;
for ( j = i + 1; j < n; j++ )
if ( list [ j ] <list [ min ] )
min = j;
SWAP ( list [ i ] , list [ min ], temp );
}
}
〖example2〗Binary search
given: a sorted list list [ n ]
serach number searchnum
return: i if list [ i ] = serachnum
-1 not present in the list
Algorithm:
while ( there are more integers to check ) {
middle = (lift +right )/2;
if ( serchnum < list[middle] )
right = middle - 1;
else if ( serchnum == list[middle])
return middle;
else left = middle + 1;
}
searchnum ~ list[middle]
< = >
right=middle -1 i lefit=middle +1
program:
for comparing:
1. macro version
#define compare(x,y) ((x) < (y)? -1:((x) == (y)) ? 0:1)
2. function version
int compare ( int x, int y );
{ /* compare x and y, return -1 for less than, 0 for equal, 1 for
greater*/
if ( x < y ) return -1;
else if ( x == y ) return 0;
else return 1;
}
int binsearch ( int list [ ], int searchnum , int left, int right )
{ /* search list [ 0 ] <= list [ 1 ] <= ··· <= list [ n-1 ] for searchnum.
Return its position if found . Otherwise return -1*/
int middle ;
while ( left <= right ) {
middle = ( left + right ) / 2;
switch ( COMPARE ( list [ middle ] , searchnum )) {
case -1 : left = middle + 1 ;
break;
case 0 : return middle;
case 1 : right = middle - 1;
}
}
return -1;
}
Recursive algorithm
FACTORIAL
n! = n·(n-1)! n>1 ( 0! = 1)
n! = n·(n-1)·(n-2) … 3·2·1
MULTIPLY
a·b = a·(b-1) + a (a·1 = a)
a·b = a·(b-1) + a = a·(b-2) +a +a = a·(b-3) + a + a +a …
=a+a+ … +a+a (b times addition)
FIBONACCI NUMBER
fib (n) = n n=0 or n=1
fib (n) = fib(n-2) + fib(n-1) otherwise
FUNCTION F1 F2 --- Fn
〖example 4〗permutation
o a,b,c t -------> o (a,b,c),(a,c,b),(b,a,c),(b,c,a),(c,a,b),(c,b,a) t
o a,b,c,d t -------> a+ all permutation of (b,c,d)
b+ all permutation of (a,c,d) --> 4·6 permutations
c+ all permutation of (a,b,d)
d+ all permutation of (a,b,c)
?Exercises
data type ------ a collection of objects and a set operations that act on
those objects.
criteria
(1) Does the program meet the original specifications of the task?
(2) Does it work correctly?
(3) Does the program contain documentation that shows how to use
it and how it work?
(4) Does the program effectively use functions to create logical units?
(5) Is program's code readable?
【definition】the space complexity of a program is the amount of memory that it needs to run
to completion.The time complexity of program is the amount of computer time that is need to
run to completion.
S(P) = C + Sp( I )
T(p) The sum of a program, p, compile time and run (or execution) time
T(p) not dependent solely on the number of inputs or outputs or some other easily specified
characteristic.
The best case step count --- the minimum number of steps
The worst case step count --- the maximum number of steps
The average case step count --- the average number of steps
count = 2n + 3
count = 2n + 2
Total 2n+2
Matrix addition
total 2*rows*cols+2rows+1
《1》Ο
【definition】f(n)
= Ο(g(n)) iff there exist positive constants c
and n0 such that f(n) <= cg(n) for all n, n>=n0
3n + 2 = Ο(n) 3n + 2 <= 4n for n >=2 c = 4 , n0=2
10 N 2 +4n + 2=Ο( n ) 10 N 2 +4n + 2 <=11 N 2
2
for n >=5 c =11,
n0=5
6* 2 n + N 2 =O( 2 )
n
6 2 n + N 2 <=7* 2 n for n >=4 c =7 , n0=4
2
3n + 3=Ο( n )2
3n+3 <=3 N for n >=2 c =3 , n0=2
3n+2 ≠ Ο(1) c, n0 not exist
10 N +4n +2 ≠ Ο(n)
2
c, n0 not exist
2
????????logn????O?n?????O?nlogn???O? n ) O? n )
3
?? 2 ) n
《2》Ω
【definition】f(n)
= Ω(g(n)) iff there exist positive constants c
and n0 such that f(n) >= cg(n) for all n, n>=n0
《3》Θ
【definition】f(n) = Θ(g(n)) iff there exist positive constants c1, c2
and n0 such that c1 g(n) <= f(n) <= c2 g(n) for all n, n>=n0
6* 2 n + N 2 =Θ( 2 )
n
【Theorem1.4】If f(n) = am N m + ……+a1n +a0 then f(n)=Θ( n
m
)
【example】Complexity of matrix addition
Total Θ(rows.cols)
【example】Binary search
n --- the number of elements in the list
worst case Θ(logn)
【example】Permutation
i=n Θ(n)
i<n Θ( n + Tperm (i + 1,n))
【example】Magic square
row sum = column sum = diagonals sum
15 8 1 24 17
16 14 7 5 23
22 20 13 6 4
3 21 19 12 10
9 2 25 18 11
#include <stdio.h>
#define MAX_SIZE 15 /*maximum size of square*/
void main(void) /* construct a magic square, interactively*/
{
static int square[MAX_SIZE][MAX_SIZE];
int i, j, row, column; /*indices*/
int count; /* counter */
int size; /* square size */
printf ("Enter the size of the square : ");
scan ("%d", &size);
/* check for input errors */
if (size < 1 || size > MAX_SIZE + 1 ) {
printf( stderr, "Error! size is out of range\n"); /* Ο(1) ∗/
exit (1);
}
if (!(size % 2) ) {
printf(stderr, "Error! size is even\n");
exit(1);
}
for(i = 0; i < size; i++)
Coxeter's rule:
1. put a one in the middle box of the top row
2. go up and left assigning number in the increasing order to
empty box
jump off the square
occupied
instance characteristic n
time name 1 2 4 8 16
32
1 constant 1 1 1 1 1 1
l ogn logarithmic 0 1 2 3 4 5
n linear 1 2 4 8 16
nlogn log linear 32
N2 quadratic 0 2 8 24 64
cubic 160
3
n
1 4 16 64 256
1024
1 8 64 512 4096
32768
2n exponential 2 4 16 256 65536
n! factorial 4294967296
1 2 24 40326 2092278988000
26313* 10 33
# include <time.h>
clock_t start, stop (call clock() )
double duration
duration = ((double) ( stop - star)) / CLK_TCK <second>
# include <time.h>
time_t start, stop (call time (null) )
double duration
duration = (double) ( difference (stop,star)) <second>
#include<stdio.h>
#include <time.h>
#define MAX_SIZE 1601
#define INTERACTIONS 26
#define SWAP(x, y, t ) ((t) = (x), (x) = (y), (y) = (t)))
void main (void)
{
int i, j, position;
int list[MAX_SIZE];
int sizelist[ ] = {1,10,20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400,
500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400,
1500, 1600};
clock_t start, stop;
double duration;
printf (" n time\n");
for ( i =0; i < interactions; i++ ) {
for ( j =0; j <sizelist [ i ]; j ++ )
list [ j ] = sizelist [ i ] - j ;
star = clock ( );
sort ( list, sizelist [ i ]);
stop = clock ( );
/* CLK_TCK = number of clock ticks per second */
duration = ((double ) ( stop - start )) / CLK_TCK;
printf ("%6d %f \ n", sizelist[ i ], duration);
}
}
n time n time
30 …100 .00 900 1 .86
200 .11 1000 2.31
300 .22 1100 2.80
400 .38 1200 3.35
500 .60 1300 3.90
600 .82 1400 4.54
700 1.15 1500 5.22
800 1.48 1600 5.93
7
6
5
4
3
2
1
0 500 1000 1500 2000
#include<stdio.h>
#include <time.h>
#define MAX_SIZE 1001
#define INTERACTIONS 16
int segsearch( int [ ], int, int);
void main (void)
{
int i, j, position;
int list[MAX_SIZE];
int sizelist[ ] = { 0, 10,20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 400,
600, 800, 1000};
int numtimes [ ] = {30000, 12000, 6000, 5000, 4000,4000,4000, 3000,
3000, 2000, 2000,1000, 500, 500, 500, 200};
clock_t start, stop;
double duration, total;
for ( i =0; i < MAX_SIZE; i++ )
list [ i ] = i ;
for ( i =0; i < interactions; i++ )
star = clock ( );
for ( j =0; j < numtimes; j++ ) {
position = segsearch ( list, -1, sizelist[ i ] );
stop = clock ( );
/* CLK_TCK = number of clock ticks per second */
total = ((double ) ( stop - start )) / CLK_TCK;
printf ("%5d %d %d %f %f \ n", sizelist[ i ], numtimes [ i ],
int (stop -start), total, duration);
list [ sizelist[ i ]] = sizelist[ i ]; /*reset value */
}
}
CHAPTER 4 LISTS
4.1 Pointers
other operations:
wise programming:
1) set all pointers to NULL when they are not actually pointing
to an object.
the null pointer is represented by the integer 0
2) use explicit type casts when converting between pointer
types
pi = malloc( sizeof (int)); /* assign to pi a pointer to int */
pf = (float * ) pi; /* cast an int pointer
to a float pointer */
3) define explicit return type for function
4) using dynamically allocated storage (malloc, free)
int i, *pi;
float f, *pf;
pi = (int *) malloc(sizeof(int));
pf = (float *) malloc(sizeof(float));
*pi = 1024;
*pf = 3.14;
printf ("an integer = %d, a float = %f \n", *pi, *pf );
free(pi);
free(pf);
4.2 Singly Linked Lists
ptr
bat cat sat vat null
ptr
bat cat sat vat null
mat
ptr
bat cat mat sat vat null
62
〖example〗list of words ending in at
define a node structure --
typedef struct list_node *list_pointer;
typedef struct list_node
{
char data [ 4 ];
list_pointer link;
};
list_pointer ptr = NULL;
place a word into the list ----- strcpy ( ptr ->data, "bat");
ptr -> link = null;
address of
first node ptr->data ptr->link
b a t \0
ptr
〖example〗Two-node linked list
typedef struct list_node *list_pointer;
typedef struct list_node {
char data ;
list_pointer link;
};
list_pointer create2()
{
/* create a linked list with two nodes */
list_pointer first, second;
first = (list_pointer)malloc(sizeof(list_node));
second = (list_pointer)malloc(siezof(list_node));
63
second->link = NULL;
second->data = 20;
first->data = 10;
first->link = second;
return first;
}
ptr
10 20 null
〖example〗List insertion
Two node list after the function call insert (&ptr, ptr)
ptr
10 20 null
node
temp 50
64
〖example〗list deletion
65
4.3 Dynamically Linked Stacks and Queues
Linked Stacks
66
stack_pointer temp = (stack_pointer)malloc(sizeof(stack));
if ( IS_FULL(temp) ) {
fprintf( stderr, "The memory is full\n");
exit(1);
}
temp->item = item;
temp->link = *top;
*top = temp;
}
Linked Queues
67
typedef struct queue {
element item;
queue_pointer link:
};
queue_pointer front [ MAX_STACKS ]; rear [ MAX_STACKS ];
68
{
/* delete an element from the queue */
queue_pointer temp = *front;
element item;
if ( IS_EMPTY(*front) ) {
fprintf(stderr, "The queue is empty\n");
exit(1);
}
item = temp->item;
*front = temp->link;
free(temp);
return item;
}
4.4 Polynomials
A( x ) = am−1 X em−1 +..... + a0 X e0
ai are nozero coefficients
ei are nonnegative integer exponents such that
em −1 > em − 2 > . . . > e1 > e0 ≥ 0
b 8 14 -3 10 10 6 null
69
(1) Adding Polynomials (d=a+b)
a->expon == b->expon
3 14 2 8 1 0 null
a
8 14 -3 10 10 6 null
b
11 14 null
d
a->expon < b->expon
3 14 2 8 1 0 null
a
8 14 -3 10 10 6 null
b
11 14 -3 10 null
d
a->expon > b->expon
3 14 2 8 1 0 null
a
8 14 -3 10 10 6 null
b
11 14 -3 10 2 8 null
d
70
b = b->link;
break;
case 0: /* a->expon = b->expon */
sum = a->coef + b->coef;
if ( sum ) attach(sum, a->expon, &rear);
a = a->link; b = b->link; break;
case 1: /* a->expon > b->expon */
attach(a->coef, a->expon, &rear);
a = a->link;
}
/* copy rest of list a and then list b */
for ( ; a; a = a->link ) attach(a->coef, a->expon, &rear);
for ( ; b; b = b->link ) attach(b->coef, b->expon, &rear);
rear->link = NULL;
/* delete extra initial node */
temp = front; front = front->link; free(temp);
return front;
}
71
*ptr = temp;
}
Time complexity (m + n)
A( x ) = am −1 X e + ..... + a0 X e
m −1 0
B ( x ) = bn−1 X f + ..... + b0 X f
m −1 0
1.coefficient additions
0 <= number of coefficient additions <= min [m, n ]
mix -- none of the exponent are equal
max -- exponents of polynomial are a subset
of the exponents of the other
2.exponent comparisons <= m+n
3.creation of new nodes for d <= m+n
(2)Erasing Polynomials
circular list ----- the link field of the last node points to
the first node in the list
ptr = 3 X 14 + 2 X 8 + 1
3 14 2 8 1 0 null
ptr
72
Program: get_node function
poly_pointer get_node(void)
/* provide a node for use */
{
poly_pointer node;
if ( avail ) {
node = avail;
avail = avail->link;
}
else {
node = (poly_pointer)malloc(sizeof(poly_node));
if ( IS_FULL(node) ) {
fprintf(stderr, "The memory is full\n");
exit(1);
}
}
return node;
}
73
temp = (*ptr)->link;
(*ptr)->link = avail;
avail = temp;
*ptr = NULL;
}
}
avail
...
ptr
temp
...
avail
ptr 3 14 2 8 1 0
74
switch ( COMPARE(a->expon, b->expon) ) {
case -1: /* a->expon , b->expon */
attach(b->coef, b->expon, &lasted);
b = b->link;
break;
case 0: /* a->expon = b->expon */
if ( starta == a ) done = TRUE;
else {
sum = a->coef + b->coef;
if ( sum ) attach(sum, a->expon, &lastd);
a = a->link; b = b->link;
}
break;
case 1: /* a->expon > b->expon */
attach(a->coef, a->expon, &lastd);
a = a->link;
}
} while ( !done );
lastd->link = d;
return d;
}
75
lead = lead->link;
middle->link = trail;
}
return middle;
}
x1 x2 x3
a
x1 x2 x3
a
a) Inserting at the front of a list
76
node->link = node;
}
else { /* list is not empty, add new entry at front */
node->link = (*ptr)->link;
(*ptr)->link = node;
}
}
b) Finding the length of a circular list
〖example〗
77
0 ≡ 4, 3 ≡ 1 ,6 ≡ 10, 8 ≡ 9, 7 ≡ 4, 6 ≡ 8, 3 ≡ 5, 2
≡ 11, 11 ≡ 0
equivalence classes:
{0, 2,4, 7, 11}; {1, 3, 5 }; {6, 8, 9, 10 }
Equivalence algorithm
void equivalence()
{
initialize;
while ( there are more pairs ) {
read the next pair <i,j>;
process this pair;
}
initialize the output;
do
output a new equivalence class;
while ( not done );
}
void equivalence()
{ initialize seq to NULL and out to TRUE;
while ( there are more pairs ) {
read the next pair, <i,j>;
put j on the seq[i] list;
put i on the seq[j] list;
}
for ( i =0; i<n; i++)
if ( out[i] ) {
out[i] = FALSE;
78
output this equivalence class;
}
}
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
seq
data 11 3 11 5 7 3 8 4 6 8 6 0
null null null null null null
link
data 4 1 0 10 9 2
link null null null null null null
#include <stdio.h>
#include <alloc.h>
#define MAX_SIZE 24
#define IS_FULL(ptr) (!(ptr))
#define FALSE 0
#define TRUE 1
79
for ( i = 0; i<n; i++ ) { /* initialize seq and out */
out[i] = TRUE; seq[i] = NULL;
}
80
y = x->link; x->link = top; top = x; x = y;
}
else x = x->link;
}
if ( !top ) break;
/* unstack */
x = seq[top->data]; top = top->link;
}
}
}
a h0 h1 h2 h3
4 4
h0 0 2
11
1 0
h1
12
h2
2 1
-4
3 3
h3 -15
81
#define MAX_SIZE 50 /* size of largest matrix */
typedef enum (head, entry ) tagfield;
typedef struct matrix_node *matrix_pointer;
typedef struct entry_node {
int row;
int col;
int value;
};
typedef struct matrix_node {
matrix_pointer down;
matrix_pointer right;
tagfield tag;
union {
matrix_pointer next;
entry_node entry;
} u;
};
matrix_pointer hdnode [ MAX_SIZE ];
Sample input :
first line num_rows num_cols
num_terms
other lines row column
value
[0] [1]
[2]
[0] 4 4
[1] 4
[2] 0 2
[3] 11
[4] 1 0
12
2 1
82
-1
3 3
-15
matrix_pointer mread(void)
{ /* read in a matrix and set up its linked representation. An
auxiliary global array hdnode is used */
int num_rows, num_cols, num_terms, num_heads, i;
int col, col, value, last, node;
current_row = 0;
last = hdnode[0]; /* last node in current row */
for ( i = 0; i < num_terms; i++ ) {
printf("Enter row, column and value: ");
scanf("%d%d%d",&row,&col,&value);
if ( row > current_row ) {
83
/* close current row */
last->right = hdnode[current_row];
current_row = row; last = hdnode[row];
}
temp = new_node();
temp->tag = entry; temp->u.entry.row = row;
temp->u.entry.col = col;
temp->u.entry.value = value;
temp->right = temp; /* link into row list */
last = temp;
/* link into column list */
hdnode[col]->u.next->down = temp;
hdnode[col]->u.next = temp;
}
/* close last row */
last->right = hdnode[current_row];
/* close all column lists */
for ( i=0; i<num_cols; i++ )
hdnode[i]->u.next->down = hdnode[i];
/* link all head nodes together */
for ( i=0; i<num_heads-1; i++ )
hdnode[i]->u.next = hdnode[i+1];
hdnode[num_heads-1]->u.next = node;
node->right = hdnode[0];
}
return node;
}
matrix_pointer new_node(void)
{ matrix_pointer temp;
temp = (matrix_pointer)malloc(sizeof(matrix_node));
if ( IS_FULL(temp) ) {
84
fprintf(stderr, "The memory is full\n');
exit(1);
}
return temp;
}
time complexity
O(max{num_rows, num_cols } + num_terms )
= O(num_row + num_cols + num_terms )
temp = temp->right)
printf("%5d%5d%5d \n",temp->u.entry.value);
head = head->u.next; /* next row */
}
}
time complexity
O(num_row + num_terms )
85
/* erase the matrix, return the nodes to the heap */
matrix_pointer x,y,head = (*node)->right;
int i,num_heads;
/* free the entry and head nodes bu row */
for ( i = 0; i< (*node)->u.entry.row; i++ ) {
y = head->right;
while ( y != head ) {
x = y; y = y->right; free(x);
}
x = head; head = head->u.next; free(x);
}
/* free remaining head nodes */
y = head;
while ( y != *node ) {
x = y; y = y->u.next; free(x);
}
free(*node); *node = NULL;
}
time complexity
O(num_row + num_cols + num_terms )
86
llink item rlink
head node
ptr = ptr -> llink -> rlink = ptr -> rlink ->
llink
new node
87
Program: Deletion from a doubly linked circular list
node node
、 deleted
88
Chapter 5 Trees
5.1 Introduction
Pedigree Dusty
B
C D 2
E F G H I J 3
K L M 4
degree of a node --- the number of subtree of the node
degree of a tree --- the maximum degree of the nodes
in the tree
leaf (terminal node ) --- a node with degree zero
parent children sibling ancestors descendants
level high or depth
Representation of Trees
List Representation
(A ( B ( E ( K, L ) , F ), C ( G ), D ( H ( M ), I, L ) ) )
A
B C D
E F G H I L
K L M
In memory
data
B C D
E F G H I J
K L M
C
E
G D
K F
H
L
M I
J
A A A
B B B
A
A A
B
B C B C
C
::= return a
binary tree
whose left
subtree is bt1,
whose right
subtree is bt2,
and whose root
node contains
the data item.
BinTree Lchild (bt ) ::= if
( Isempty( bt ))
return error
else return
the left
subtree of bt.
element Data(bt) ::= if
(Isempty( bt ))
return error
else return
the data in
theroot node
of bt.
BinTree Rchild(bt) ::=
if( Isempty( bt
)) return
error
else return
the right
subtreeof bt.
B B
A
A
B
B C
C
D E F G
D
H I
Skewed binary tree Complete binary tree
E
Proof:
(1) The proof is by induction on i
induction base: i = 1(root)
max_num ( on level 1) = 2 = 2 = 1
i −1 0
2 3
4 5 6 7
8 9 10 11 12 13 14 15
A B -- C --
- -- -- D -- ... E
[1] [2] [3] [4] [5] [6] [7] [8] [9] ... [16]
A B C D E F G H I
[1] [2] [3] [4] [5] [6] [7] [8] [9]
Linked representation
typedef struct node *tree_pointer;
typedef struct node {
int data;
tree_pointer left_child,
right_child;
};
left_child right_child
ROOT ROOT
A NULL A
B NULL B C
NULL E NULL
2 17 E
*
3 19
* 14 D 18
4 / 11 C 16
15
5 13
A 8 B 12
10
6 7 9
(1) Recursive Traversal
Inorder Traversal
A/B*C*D+E
void inorder( tree_pointer ptr)
/* inorder tree traversal */
{
if (pr) {
inorder (ptr->left_child);
printf ("%d",ptr->data);
inorder (ptr->right_child);
}
}
Preorder Traversal
+**/AB C D E
void preorder(tree_pointer ptr)
/* preorder tree traversal */
{
if (ptr){
printf ("%d", ptr_data);
preorder (ptr->left_child);
preorder (ptr->right_child);
}
}
Postorder Traversal
A B/C*D*E+
void postorder( tree_pointer ptr)
/* postorder tree traversl */
{
if (ptr){
postorder ( ptr->left_child);
postorder ( ptr->right_child);
printf ("%d", ptr_data);
}
}
the expression: x1 ∨ ( x2 ∧ ¬ x3 ) is a
formula.
If x1 = x3 = false, x2 = true, Then the value of
the expression =
false ∨ ( true ∧ ¬ false)
= false ∨ true
= true
x3
x1 x3
x2 x2
post_order_eval function
void post_order_eval(tree_pointer node)
{ /* modified post order traversal to evaluate a
propositional
calculus tree*/
if (node){
post_order_eval (node->left_child);
post_order_eval (node->right_child);
switch (node->data) {
case not:
node->value = !node->right_child-
>value;
break;
case and:
node->value = node->right_child-
>value &&
node->left_child->value;
break;
case or:
node->value = node->right_child-
>value ||
node->left_child->value;
break;
case true:
node->value = TRUE;
break;
case false:
node->value = FALSE;
}
}
}
B C
D E F G
H I
typedef struct threaded_tree *threaded_pointer;
typedef struct threaded_tree {
short int left_thread;
threaded_pointer left_child;
char data;
threaded_pointer right_child;
short int right_thread;
};
True False
ROOT f = FALSE
f . - . f t = TRUE
f . A . f
f . B . f f . C . f
f . D . f t . E . t t . F . t t . G . t
t . H . t t . I . t
operations
A A
B parent parent
B
child
C D C D
child
( a )
root root
A A
parent parent
B B
child
C D C X
E F D
E F
child X
before after
( b )
right insertion in a threaded binary tree
threaded_pointer child)
{ /* insert child as the right child of parent in a
threaded
binary tree */
threaded_pointer temp;
child->right_child=parent->right_child;
child->right_therad=parent->right_thread;
child->left_child=parent;
child->left_thread=TRUE;
parent->right_child=child;
parent->right_thread=FALSE;
if ( !child->right_thread ) {
temp = insucc(child);
temp->left_child = child;
}
}
5.6 heaps
structure MaxHeap is
objects:a complete binary tree of n>0 elements
organized
so that the value in each node is
at least as large
as those in its children
function:
for all heap ∈ MaxHeap, item ∈
Element,
n, max_size ∈ integer
MaxHeap create(max_size) ::= create an empty
heap that
max_size elements.
Boolean HeapFull(heap,n) ::= if (n ==
max_size) return
OPERATIONS
representationinsertiondeletionunordered
arrayΘ(1)Θ(n)unordered linked listΘ(1)Θ(n)sorted
arrayO(n)Θ(1)sorted linked listO(n)Θ(1)max
heapO( log 2 n )O( log 2 n)
[1] 20 [1] 20
[1] 20 [1] 21
PROGRAM O( log 2 n )
20
removed
[1] [1] 10 [1] 15
15 25 5 40 70
12 10 22 2 65 80
5 40 5 40
2 80 2 35 80
void insert_node(tree_pointer *node, int num)
/* If num is in the tree pointed at by node do
nothing;otherwise add a new node with data = num */
{tree_pointer ptr, temp = modified_search (*node,
num);
if ( temp || !(*node)){
/*num is not in the tree */
ptr = (tree_pointer) malloc
(sizeof(node));
if (IS_FULL( ptr )){
fprintf (stderr,"The memory is full
\n");
exit(1);
}
ptr->data = num;
ptr->left_child = ptr->right_child =
NULL;
if (*node) /* insert as child of
temp */
if (num < temp->data) temp-
>left_child = ptr;
else temp->right_child = ptr;
else *node = ptr;
}
}
5 40 5 80
2 80 2
40 40
20 60 20 55
50 70 10 30 50 70
10 30
45 55 45 52
52
(a)tree before deletion of 60 (b)tree after deletion of 60
(4) Height of a binary search tree
1 6
2 3
6 8
6 7
4 5 6 8 17
9
10 11 12 13 14 15
8 9 90 17
10 9 20 6 8 9
15 20 20 15 15 11 100 18
16 38 30 25 50 16 110 20
2 3
9 8
6 7
4 5 8 17
9 15
10 12 13 14 15
8 9 11
10 9 20 15 8 9 90 17
15 20 20 25 15 11 100 18
16 38 30 25 50 16 110 20
Tree of losers
each nonleaf node retains a pointer to the
loser. An additional node, node 0, has been added
to represent the overall winner of the tournament.
overall
0 6 winner
1 8
2 6 3
9 17
6 7
4 5 20 9 90
10
10 12 13 14 15
8 9 9 11
10 20 6 8 9 90 17
run 1 2 3 4 5 6 7 8
5.9 Forests
【definition】A forest is a set of n >= 0 disjoint
trees
A
A E
B E
B C D F
C F G
G
D H
H I
I
(2) Forest Traversal
inorder
1. If F is empty, then return
2. Traverse the subtree of the first tree in tree
inorder
3. Visit the root of the first tree of F
4. traverse the remaining trees of F in inorder
preorder
1. If F is empty, then return
2. Visit the root of the first tree of F
3. Traverse the subtree of the first tree in tree
preorder
4. Traverse the remaining trees of F in preorder
postorder
1. If F is empty, then return
2. Traverse the subtree of the first tree in tree
postorder
3. Traverse the remaining trees of F in postorder
4. Visit the root of the first tree of F
0 4 2
6 7 8 1 9 3 5
9
S1 S2 S3
operations
⑴ disjoint set union. If Si and Sj are disjoint sets,
then their
union Si U Sj = { all elements, x, such that x is
in Si or Sj }.
⑵ Find( i). Find the set containing the element, i,
0 4
6 7 8 4 0 1 9
1 9 6 7 8
S1 U S2 S2 U S1
set 0
name pointer
S1 6 7 8
S2
4
S3
1 9
3 5
n-2
1 1 2
0 4 ... n-1 0
1 2 3 1 2 3 ... n-1
union(0,3), union(0,n-1)
0=find(0)
void union2( int i, int j)
{ /* union the sets with roots i and j, i != j, using the
weighting rule.parent[i] = -count [ i ] and parent[j] = -
count[j] */
int temp = parent[i] + parent[j];
if (parent[i] > parent[j]) {
parent[i] = j; /*make j the new
root */
parent[j] = temp;
}
else { parent [j] = i; /*make i the new
root */
parent [j] = temp;
}
}
〖lemma5.4〗Let T be a tree with n nodes created as
a result of union2. No node in T has level greater
then [ log 2 n ] + 1
proof:
n = 1, lemma is clearly true
i < = n - 1, assume that it is true for all trees with i
nodes
i=n, T is a tree with n noes created by
union2
last union operation union( k, j )
m ---- the number of nodes in tree j (1
<= m <= n/2 )
n - m ---- the number of nodes in k
if the max level of any node in T is
same as k
then max level in T <= [ log 2 ( n − m ) ]
+ 1 <= [ log 2 n] +1
if the max level of any node in T is one
more than in j
then max level in T <= [ log 2 m ] + 2
<= [ log 2 n / 2 ] +2 <= [ log 2 n] +1
〖example〗
initial, parent [ i ] = - count [ i ] = -1, 0 ≤ i < n = 2 3
union( 0, 1) union( 2, 3) union( 4, 5)
union( 6, 7)
union( 0, 2) union( 4, 6) union(0, 4)
[-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] level command
0 1 2 3 4 5 6 7 1 initial
[-4] [-4]
1 union(0,2)
0 4 union(4,6)
5 6 2
1 2
3 7 3
[-8]
0 1 union(0,4)
2
1 2 4
6 3
3 5
7 4
(1)
A(3,4) = 2 --
2
}65,536 twos
(2) A( p , q + 1) > A( p , q )
(3) A( p + 1, q ) > A( p , q )
[-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] lnput
0 1 2 3 4 5 6 7 8 9 10 11 initial
9
[-5] [-4] [-3]
0 11 = 0
6 3
4 2 7 10 8 1 5
11 9
2. Stack permutations
preorder sequence: ABCDEFGH I
inorder sequence: BCAEDGHF I
Does such a pair of sequences uniquely define a
binary tree ?
(a) (b)
A
A
B D,E,F,G,H,I
B,C D,E,F,G,H,I
C
A PREORDER: 123456789
1 INORDER: 213547869
B D 2 4
C E F 3 5 6
G I 7 9
H 8
(c)
1 1 1
1 1
2 2 3 2 2
2
3 3 3 3
3. Matrix Multiplication
M 1 * M 2 * .... * M n
n = 4: five possibilities: (( M 1 * M 2 ) * M 3 ) * M
4
(M 1 * ( M 2 * M 3 ) )* M
4
M 1 * (( M 2 * M 3 ) * M
4)
(M 1 * ( M 2 * ( M 3 * M
4 ) ))
(( M 1 * M 2 ) * (M 3 * M
4))
bn ----- the number of different ways to compute
the product
of n matrices ( b 1 = 1, b 2 = 2, b 3 = 5)
M ij = the product M i * M i + 1 * ... * M j ( i <=
j)
M 1n = the product M 1i * M i+1, n ( 1 <= i <= n)
M 1i = b i M i+1, n = b n - i
n−1
bn = ∑ bi bn− i n>1
i =1
b n = the number of distinct binary trees with n
nodes
b n = the sum of all the possible binary trees
formed in the
following way:
a root and two subtrees with b i and b n - i-1
nodes,
for 0 <= i <= n
bn
bi b n-i-1
n−1
bn = ∑ bi bn− i −1, n ≥ 1, and b0 = 1
i =0 Eq.(1).
xB 2 ( x ) = B ( x ) − 1
xB ( x ) = B( x ) − 1
2
Eq.(2)
Eq.(3)
B ( x ) = ∑ bi x i
is the coefficient of x
n
in B(x), is: i ≥0
1 2n L
M O
bn =
n +1 n NPQ
bn = Ο( 4 n / n3/ 2 )
Chapter6 GRAPHS
6.1 The graph abstract data type
1. introduction
Koenigsberg bridge problem
starting at some land area, is it possible to return to our staring
location after walking across each of the bridge exactly once ?
C d g
c
C
g
c d
A e
e
D A D
a b
a f
b f
B B
start B ----> (a)---> A ---> (e )---> D ---> (g) --->
C ---> (d) ---> A ---> (b) ---> B ---> (f ) ---> D [no
solution]
Eulerian walk
There is a walk starting at any vertex, going through each
edge exactly once, and terminating at the starting vertex iff the
degree of each vertex is even.
graph applications:
analysis of electrical circuits,
finding shortest routes,
project planning,
identification of chemical compounds.
1 2 1 2 1
3
3 4 5 6 2
G1 G2 G3
0 2 0
1 3
1 2
125
0 0
0 1 2
1 2 3 1 2
3
(a) some of subgraphs of G1
0 0 3 0
2 1
1
6
2
(b) some of subgraphs of G3
path from vp to vq ----- a sequence of vertices vp , vi1 , vi2 , … ,
vin , vq such that ( vp , vi1 ), ( vi1 , vi2 ),…,
( vin , vq ) are edges in an undirected graph.
in directed graph, the path consists of
< vp , vi1 >, < vi1 , vi2 >,…, < vin , vq >
length of a path ---- the number of edges on the graph
simple path ----- a path in which all vertices, except possibly
the first and the last are distinct.
simple directed path
cycle ---- a simple path in which the first and the last vertices
are the same.
directed cycle
v0 and v1 are connected ----- there is a path from v0 to v1
an undirected graph are connected ------
if , for every pair of distinct vertices vi , vj ,
there is a path from vi to vj in G.
H1 0 H2 4
2 1 5
3 6
7 G4
126
that is connected and acycle)
127
List Adjacent( graph, v ) ::= return a list of all
vertices hat are adjacent to v.
2. representations
⑴ adjacency matrix
0 1 2 3 4 5 6 7
0 1 2 3 0 0 1 1 0 0 0 0 0
0 1 2 1 1 0 0 1 0 0 0 0
0 0 1 1 1 0 0 1 0 2 1 0 0 1 0 0 0 0
1 1 0 1 1 1 1 0 1 3 0 1 1 0 0 0 0 0
2 1 1 0 1 2 0 0 0 4 0 0 0 0 0 1 0 0
3 1 1 1 0 5 0 0 0 0 1 0 1 0
6 0 0 0 0 0 1 0 1
G1 G3 7 0 0 0 0 0 0 1 0
G4
n−1
the degree of any vertex, i : ∑ adj _ mat [ i ][ j ]
j =0
⑵ Adjacency list
headnodes vertex link
1 0 1 2 null
0 2 3 null
1 0 2 1 0 3 null
3 null
2 0 1 3 null 2 0 3 null
3 0 1 2 null 3 1 2 null
G1 4 5 null
0 1 null 5 4 6 null
1 0 2 null 6 5 7 null
2 null 7 6 null
G3
G4
128
#define MAX_VETICES 50 /* maximum number of vertices */
typedef struct node *node_pointer;
typedef struct node { int vertex;
struct node *link;
};
node_pointer graph[MAX_VERTICES];
int n= 0 ; /* vertices currently in use */
the degree of any vertex ---- the number of nodes in the its
adjacency list
the total number of edges in G ---- Ο( n + e )
129
0 1 null
tail head column link for haed row link for tail
headnodes
(shown twice) 0 1 2
0 0 1 null
1 1 0 null 1 2 null
2 null G3
0 3 1 2 null
1 2 0 3 null
2 3 0 1 null
3 2 1 0 null
G1
⑶ Adjacency multilists
130
};
edge_pointer graph [MAX_VERTICES];
headnode
0 M1 0 1 M2 M4 edge(0,1)
1
2 M2 0 2 M3 M4 edge(0,2)
3
M3 0 3 null M5 edge(0,3)
M4 1 2 M5 M6 edge(1,2)
M5 1 3 null M6 edge(1,3)
#define FALSE 0
#define TRUE 1
short int visited [MAX_VERTICES];
void dfs(int v)
{
/* depth first search of a graph beginning with vertex v */
node_pointer w;
visited[v] = TRUE;
printf ("%5d",v);
for (w = graph[v]; w; w = w->link)
131
if ( !visited [ w->vertex ])
dfs( w->vertex );
}
〖example〗
0 1 2 null
v0
1 0 3 4 null
2 0 5 6 null v1 v2
3 1 7 null
v3 v4 v5 v6
4 1 7 null
5 2 7 null
v7
6 2 7 null
7 3 4 5 6 null
complexity
for adjacency list , O (e) for adjacency matrix , O
(n )
2
132
}
}
}
complexity
for adjacency list , O (e)
for adjacency matrix , O ( n )
2
⑶ Connected components
void connected(void)
{
/* determine the connected components of a graph */
int i;
for ( i=0; i < n; i++)
if ( !visited [ i ] ) {
dfs ( i );
printf ( "\n" );
}
}
complexity
for adjacency list , O(n+e)
for adjacency matrix , O ( n )
2
⑷ Spanning trees
spanning tree is any tree that consists solely of edge in G
and that includes all the vertices in G.
133
v0 v0
v2 v0 v2
v0
v5 v6 v3 v4 v5 v6
v3 v4
v7 v7
(a) dfs(0) spanning tree (b) bfs(0) spanning tree
property1 :
property2 :
134
articulation points --- a vertex v of G such that the deletion of
v, together with all edges incident on v, produces a graph, G',
that has at lest two connected components.
8 9 0 8 9
0
1 7 7
1 7
1 7
2 3 5
2 3 3 5 5
4 6
4 6
(a) connected graph (b) biconnected components
135
0
3
9 8 9 8 1 5
4 0
4 5
3 1 7 7
0 5 2 2 6 6
2
2 3 5
3 1
7 7
4 6 9
1 6 4 8
0 9 8
definition: low
for each vertex of G such that low(u) is the lowest depth first
number that we can reach from u using a path of
descendants followed by at most one back edge:
□u is an articulation point
iff u is either the root of the spanning tree and has two or
more children, or u is not the root and u has a child w such
that low(w) >= dfn(u).
vertex 0 1 2 3 4 5 6 7 8 9
dfn 4 3 2 0 1 5 6 7 9 8
136
low 4 3 0 0 0 5 5 7 9 8
global declarations:
137
void bicon( int u, int v) O(n + e )
{
/* compute dfn and low,and output the edges of G by their
biconnected component, v is the parent (if any) of the u
{if any) in the resulting spanning tree.It is assumed that
all entries of dfn[] have been initialized to -1,num has
been initialized to 0,and the stack has been set to empty
*/
node_pointer ptr;
int w,x,y;
dfn[u] = low[u] = num++;
for (ptr = graph[u]; ptr; ptr = ptr->link){
w = ptr->vertex;
if(v!= w && dfn[w] < dfn[u])
add (&top, u, w); /* add edge to
stack */
if ( dfn [ w ] m< 0) { /* w has not been
visited * /
bicon(w,u);
low[u] = MIN2(low[u],low[w]);
if (low[w] >= dfn[u]{
printf ("New biconnected component:");
do { /* delete edge from stack */
delete (&top, &x, &y);
printf (" <&d,&d>",x,y);
} while ( !((x == u) && ( y == w)));
printf ("\n");
}
}
else if (w != v) low[u] = MIN2(low[u], low[w]);
}
}
138
greedy method ( design strategy ):
Kruskal's Prim's sollin algorithms
Kruskal's algorithms
Kruskal's algorithm
T={ };
while (T contains less than n-1 edges && E is not empty ){
choose a least cost edge (v,w) from E;
delete (v,w) from E;
if ((v,w) does not create a cycle in T)
add (v,w) into T;
else
discard (v,w);
}
if (T contains fewer than n-1 edges)
printf ("No spanning tree\n");
〖example〗
139
0 0 0
28
10 10 1
1 1
14 16
5 6 2 5 6 2 5 6 2
24
25 18
4 12 4 4
22 3 3 3
4 12 4 12 4 12
3 3 3
(g) (h)
140
〖theorem 6.1〗let G be an undirected connected graph.
Kruskal's algorithm generates a minimum cost spanning tree.
proof :
(a) Kruskal's method produces a spanning tree whenever
a
spanning tree exist
(b) the spanning tree generated is of minimum cost
Prim's algorithm
T={ };
TV = { 0 }; /* start with vertex 0 and no edges */
while (T contains fewer than n-1 edges) {
let (u,v) be a least cost edge such that u ∈ TV and
v ∉ TV;
if (there is no such edges)
break;
add v into T;
add (u, v) into T;
}
if (T contains fewer than n-1 edges)
printf("No spanning tree\n");
141
0 0 0
10 1 10 10
1 1
5 6 2 5 6 2 5 6 2
25 25
4 4 4
3 3 22 3
0 0
0
10 10 10 1
1 1 14 16
16
5 5 6 2 5 6 2
6 2
25 25 25
12 12 4 12
4 4
3 3 22 3
22 22
(d) (e) (f)
Sollin's algorithm
0 0
10 10
1 1
14 14 16
5 6 2 5 6 2
25
4 12 4 12
22 3 22 3
(a) (b)
142
6.4 Shortest path and transitive closure
greedy method:
1.Let S denote the set of vertices, including v0, whose
shortest paths have been found
2. For w in not in S, let distance[w] be the length of the
shortest path starting from v0, going through vertices
only
in S, and ending in w.
□If the next shortest path is to vertex u, then the path from v0
to u goes through only those vertices that are in S.
□Vertex u is chosen so that it has the minimum distance,
distance[u], among all the vertices not in S.
□ Once we have selected u and generated the shortest path
from v0 to u, u becomes a member of S. (w is not currently
in S) the shortest path = distance [ u ] + length (<u, w> )
45
v0 50 10 v4 path lenght
v1
1) v0 v2 10
20 10 15 35 2) v0 v2 v3 25
20 30 3) v0 v2 v3 v1 45
4) v0 v4 45
v2 v3 v5
15 3
143
#define MAX_VERTICES 6 /* maximum number of vertices */
int cost[ ][MAX_VERTICES} =
{{ 0, 50, 10,1000, 45,1000},
{1000, 0, 15,1000, 10,1000},
{ 20,1000, 0, 15,1000,1000},
{1000, 20,1000, 0, 35,1000},
{1000,1000, 30,1000, 0,1000},
{1000,1000,1000, 3,1000, 0}};
int distance[MAX_VERTICES];
short int found[MAX_VERTICES];
int n = MAX_VERTICES;
144
/* find the smallest distance not yet checked */
int i,min,minpos;
min = INT_MAX;
minpos = -1;
for (i=0; i<n; i++)
if (distance[i] < min && !found [i]){
min =distance[i];
minpos = i;
}
return minpos;
}
〖example〗
4 Boston
1500
Chicago 250
San 3
francisco Denver 1200
800 1000
1 2 5
0 1700 900
0 1 2 3 4 5 6 7
0 0
1 300 0
2 1000 800 0
3 1200 0
4 1500 0 250
5 1000 0 900 1400
6 0 1000
7 1700 0
145
{4} 5 +∞ +∞ +∞ 1250 0 250 1150 1650
1
{4,5} 6 +∞ +∞ +∞ 1250 0 250 1150 1650
2
{4,5,6} 3 +∞ +∞ 2450 1250 0 250 1150 1650
3
{4,5,6,3} 7 3350 +∞ 2450 1250 0 250 1150 1650
4
{4,5,6,3,7} 2 3350 3250 2450 1250 0 250 1150 1650
5
{4,5,6,3,7,2} 1 3350 3250 2450 1250 0 250 1150 1650
6
{4,5,6,3,7,2,1} 3350 3250 2450 1250 0 250 1150 1650
Ak [ i ][ j ] = min{ Ak −1 [ i ][ j ], Ak −1 [ i ][ k ] + Ak −1 [ k ][ j ]}, k ≥ 0
A−1 [ i ][ j ] = cost [i ] [j ]
146
〖example〗
0
-2
1 2
L
M
0 1 ∞ O
P
1 −2 A−1
1
M
M
0 1
P
P
N∞ ∞ ∞ Q
A1 [0][2] ≠ min{ A1 [0][2], A0 [0][1] + A0 [1][2] } = 2
A1 [0][2] = ∞ ( path 0,1,0,1, 0,1, …, 0, 1, 2 )
〖example〗
V0 V1 0 1 2
0 0 4 11
1 6 0 2
V2 2 3 0
147
-1 0 1 2
A A A 0 1 2 A 0 1 2
0 1 2 0 1 2
0 0 4 11 0 0 4 11 0 0 4 6 0 0 4 6
1 6 0 2 1 6 0 2 1 6 0 2 1 5 0 2
2 3 0 2 3 7 0 2 3 7 0 2 3 7 0
⑶ transitive closure
+
【definition】 The transitive closure matrix , denoted A , of a
+
directed graph, G, is a matrix such that A [i][j] = 1 if there is
+
a path of length > 0 from i to j : otherwise, A [i][j] = 0.
【definition】 The reflexive closure matrix , denoted A*, of a
directed graph, G, is a matrix such that A* [i][j] = 1 if there is
a path of length >= 0 from i to j : otherwise, A* [i][j] = 0.
0 1 2 3 4
0 0 1 0 0 0 0 0 1 1 1 1 0 1 1 1 1 1
1 0 0 1 0 0 1 0 0 1 1 1 1 0 1 1 1 1
2 0 0 0 1 0 2 0 0 1 1 1 2 0 0 1 1 1
3 0 0 0 0 1 3 0 0 1 1 1 3 0 0 1 1 1
4 0 0 1 0 0 4 0 0 1 1 1 4 0 0 1 1 1
+ A*
A A
by using allcosts A+ --> A*
--> Ο( n3 )
simplify the algorithm : Ο( n ) (for undirected graph)
2
distanve[ i ][ j ] =
distanve[ i ][ j ] || distanve[ i ][ k ] && distanve[ k ][ j ]
148
course course name prerequisites
c1 programming 1 none
c2 discrete mathematics none
c3 data structure c1,c2
c4 calculus I none
c5 calculus II c4
c6 linear algebra c5
c7 analysis of algorithm c3,c6
c8 assembly language c3
c9 operating system c7,c8
c10 programming language c7
c11 compiler design c10
c12 artificial intelligence c7
c13 computational theory c7
c14 parallel algorithms c13
c15 numerical analysis c5
C9
C8
C1
C10 C11
C3
C7
C2 C12 C14
C6 C13
C4 C5
C15
149
C1,C2,C4,C5,C3,C6,C8,C7,C10,C13,C12,C14,C15,C11,C9 and
C4,C5,C2,C1,C6,C3,C8,C15,C7,C9,C10,C11,C12,C13,C14
algorithm
1. list out a vertex in the network that has no predecessor
2. delete this vertex, and all edges leading out from it, from
the network.
3. repeat 1, 2, until either all the vertices have been listed, or
all remaining vertices have predecessors and so we
cannot
remove any of them.
V1 V1 V1 V1 V1 V4
V0 V2 V4 V2 V4 V2 V4 V4 V4
V3 V5 V3 V5 V5 V5
150
typedef struct node *node_pointer;
typedef struct node { int vertex;
node_pointer link;
};
typedef struct { int count;
node_pointer link;
} hdnodes;
hdnodes graph[ MAX_VERTICES ]
151
}
}
V0 0 1 2 3 null
V1 1 4 null
V2 1 4 5 null
V3 1 5 4 null
V4 3 null
V5 2 null
n−1
complexity Ο (( ∑ d i ) + n ) = Ο ( e + n )
i =0
152
activity may start without increasing the project duration
early( i ) = earliest [ k ]
late ( i ) = latest [ l ] - duration of activity ai
earliest [ 0 ] = 0
earliest [ j ] = max
i ∈P ( j ) { earliest [ i ] + duration of < i, j > }
P(j) is the set of immediate predecessors of j
V0 0 1 6 2 4 3 5 null
V1 1 4 1 null
V2 1 4 1 null
V3 1 5 2 null
V4 2
6 9 7 7 null
V5 1 7 4 null
V6 1 8 2 null
V7 2 8 4 null
V8 2 null
153
earliest [0] [1] [2] [3] [4] [5] [6] [7] [8] stack
initial 0 0 0 0 0 0 0 0 0 [0]
output v0 0 6 4 5 0 0 0 0 [3,2,1]
output v3 0 [5,2,1]
output v5 0 6 4 5 0 7 [2,1]
output v2 0 0 0 [1]
output v1 0 6 4 5 0 7 [4]
output v4 0 11 0 [7,6]
output v7 0 6 4 5 5 7 [6]
output v6 0 11 0 [8]
output v8 0 6 4 5 7 7
0 11 0
0 6 4 5 7 7
16 14 0
0 6 4 5 7 7
16 14 16
0 6 4 5 7 7
16 14 18
154
V0 3 null
V1 1 0 6 null
V2 1 0 4 null
V3 1 0 5 null
V4 2 1 1 2 1 null
V5 1
3 2 null
V6 1 4 9 null
V7 1 4 7 5 4 null
V8 0 6 2 7 4 null
latest [ 8 ] = earliest [ 8 ] = 18
latest [ 6 ] = min { earliest [ 8 ] - 2 } = 16
latest [ 7 ] = min { earliest [ 8 ] - 4 } = 14
latest [ 4 ] = min { earliest [ 6 ] - 9 , earliest [ 7 ] - 7} = 7
latest [ 1 ] = min { earliest [ 4 ] - 1 } = 6
155
latest [ 2 ] = min { earliest [ 4 ] - 1 } = 6
latest [ 5 ] = min { earliest [ 7 ] - 4 } = 10
latest [ 3 ] = min { earliest [ 5 ] - 2 } = 8
latest [ 0 ]
= min { earliest [ 1 ] - 6,earliest [ 2 ] - 4,earliest [ 3 ] - 5 } = 0
156
chapter 9 heap structures
9.1 Min-Max heap
7 min
70 40 max
30 9 10 15 min
45 50 30 20 12 max
212
if (item.key > heap[grandparent].key) {
heap[i] = heap[grandparent];
i = grandparent;
grandparent /= 4;
}
else
break;
heap[i] = item;
}
7 min
70 40 max
30 9 10 15 min
45 50 30 20 12 j max
inserting 5
5 min
70 40 max
30 9 7 15 min
45 50 30 20 12 10 max
inserting 80
7 min
70 80 max
30 9 10 15 min
45 50 30 20 12 40 max
213
(2) deletion of min element
12 min
70 40 max
30 9 10 15 min
45 50 30 20 max
9 min
70 40 max
30 12 10 15 min
45 50 30 20 max
214
element delete_min(element heap[ ], int *n)
{ /* delete the minimum element from the min-max heap:
O(log n) */
int i, last, k, parent;
element temp, x;
if ( !(*n) ) {
fprintf(stderr,"The heap is empty\n");
heap[0].key = INT_MAX; /* error key in heap[0] */
return heap[0];
}
heap[0] = heap[1]; /* save the element */
x = heap[ (*n)-- ];
/* find place to insert x */
for ( i = 1, last = (*n)/2; i <= last;) {
k = min_child_grandchild(i, *n);
if (x.key <= heap[k].key) break;
/* case 2(b) or 2(c) */
heap[i] = heap[k];
if (k <= 2*i+1) { /* 2(b) */
i = k;
break;
}
/* case 2(c), k is a grandchild of i */
parent = k/2;
if (x.key > heap[parent].key)
SWAP(heap[parent],x,temp);
i = k;
} /* for */
heap[i] = x;
return heap[0];
}
215
9.2 deaps
if ( j > n ) j /= 2
5 45
10 8 25 40
15 19 9 30 20
216
5 45
10 8 25 40
15 19 9 30 20
i j
insertion of 4
4 45
5 8 25 40
15 10 9 30 20 19
insertion of 30
5 45
10 8 30 40
15 19 9 30 20 25
functions
• max_heap ( n )
this function return TRUE iff n is a position in the
max-heap of the deap.
• min_partner ( n )
This function compute the min_heap node that
corresponds to the max-heap position n. This is given by
[log n]−1
n- 2 2
• max_partner ( n )
217
This function compute the max-heap node that
corresponds to the parent of min-heap position n. This is
[log n]−1
given by ( n - 2 2
)/2
218
else
max_insert(deap,*n,x);
}
}
8 45
10 9 25 40
15 19 20 30
219
j = i*2;
if (j+1 < = *n) {
if (deap[j].key > deap[j+1].key)
j++;
}
}
modified_deap_insert(deap , i , temp);
return deap[0];
}
A G
B C H I
D E F J
2 2
A G
2 1 1 1
B C H I
1 1 1
D E F J
shortest ( x ) =
R
So if x is an external node
T1+ min{ shortest ( left _ child ( x )), shortest ( right _ child ( x ))} otehrwise
【definition】
A leftist tree is a binary tree such that iff it is not empty,
then
shortest (left_child(x)) >= shortest(right_child(x))
220
for every internal node x
〖Lemma9.1〗
Let x be the root of a leftist tree that has n (internal ) nodes.
(a) n >= 2
shortest ( x )
-1
(b) The rightmost root to external node path is the shortest
root to external node path. Its length is shortest( x ).
typedef struct {
int key;
/* other field */
} element;
typedef struct leftist *leftist_tree;
struct leftist {
leftist_tree left_child;
element data;
leftist_tree right_child;
int shortest;
};
【definition】 A min-leftist tree (max leftist tree) is a leftist tree
in which the key value in each node is no large ( smaller ) than
the key value in its children ( if any ). In other words. a min (max)
leftist tree is a leftist that is also a min ( max ) tree
2 2
2 a 5 b
1 1 1 1
7 50 9 8
1 1 2 1
11 80 12 10
1 1 1 1
13 20 18 15
221
delete the min element <-- a
• combine a->left_child and a->right_child
• delete node a
combine a and b
• obtain a new binary tree containing all elements in a
and b following the rightmost path in a and/or b. (the key in
each node is no larger than the key in its children )
• interchange the left and right subtree of nodes as
necessary to convert this binary tree into a leftist tree
2
5
2 2
8 1
1 1 9 8
2 1 1
10 50
1 1 12 10 50
1 1 1 1
15 80
20 18 15 80
2 2
2 2
1 2 1
7 5 5 71
1 1 2 2 1
11 9 8 8 9 11 1
1 1 1
2 1 1 2
13 12
1
10 50
1
10 50 12 13 1
1 1 1 1 1 1
20 18 15 80 15 80 20 18
222
else if (*b)
min_union(a , b);
*b = NULL;
}
individual operation:
binomial heap ~ O ( n )
223
leftist tree ~ O ( log n )
amortize part of the cost of expensive operation over the
inexpensive once ~ O ( 1 ) or O ( log n )
amortize scheme :
charge some of the actual cost of an operation to other
operations. This reduce the charged cost of some operations
and increases that of others
〖example〗
operation sequence: I1,I2,D1,I3,I4,I5,I6,D2,I7
actual cost: I1 ~ I7 -- 1, D1 - 8, D2 -- 10 ( unit of
time )
total cost = 25
if 2 units (D1) --> I1, I2, 4 units ( D2) --> I2 ~ I6
the amortized cost of each of I1 ~ I6 = 2 units
the amortized cost of each of D1 ~ C2 = 6 units
the total amortized cost = (2*6+1*+2*6 ) = 25 units
224
1
3
8 12 7 16
5 4
10 15 30 9
6
20
insert, combine -- O (1) (actual , amortized time )
delete -- O ( log n ) ( amortized time )
B-heap representation : doubly linked list
field: degree, child, left_link, right_link, data
a
8 3 1
5 4 12 7 16
10
6 15 30 9
20
(3) insertion into a binomial heap O (1)
element x --> B-heap a
1. putting x into a new node
2. placing this node into the doubly linked circular list
pointer at by a
3. if a is null or x's key < the key in the node pointed by a
then reset a to the new node
225
linked circular list; Now, a pointer to any
remaining
node in the resulting list; If there is no such
node,
then a = NULL
step3: [Min-tree joining]
Consider the min-tree in the list a and y; joining
together pairs of min-tree of the same degree
until
all remaining min-trees has different degree;
step4: [Form min-tree root list]
Link the roots of the remaining min-tree ( if any )
together to form a doubly linked circular list;
Set a
to point the root ( if any ) with minimum key;
new
B-heap consist of the remaining min-tree and
the
sub min-tree of the deleted root
8 3 12 7 16
5 4 15 30 9
10
6 20
making the min-tree whose root has larger key a subtree of the other
7 3 12 16
8 9 5 4 15 30
6 20
10
226
3 12 16
7 5 4
15 30
8 9 6
20
10
(6) analysis
227
Fibonacci heap:
min-Fibonacci heap is a collection of min-tree ( F-heap )
max-Fibonacci heap is a collection of max-tree
operations:
the deletion of 12
228
8 3 1 15 30
5 4 7 16 20
10
6 9
the reducetion of 15 by 4
8 3 1 11
5 4 7 16 20
12
10
6 30 9
229
□each time two min-tree are joined in a delete min
operation, the child_cut of the root with larger key = False
2
14 12 10
F
4 5
16 15
T 18 30 11
6 60
T
20 8 7
8 6
T
10
20 7
T
30 12 11
2
*
14 18 4 5
16 15 60
(4) Analysis
〖Lemma9.3〗 Let a be an F-heap with n elements that
results from a sequence of insert, combine, delete min, delete,
and decrease key operations performed on initially empty F-
heap
(a) Let b be any node node in any of the min-trees of a.
The degree of b is at most log φ m , where
φ = ( 1+ and m is the number of elements in the
5 ) / 2
subtree with root b.
(b) MAX_DEGREE ≤ [ log φ m ] and the actual cost of a delete
230
min is O(log n + s)
〖Theorem9.2〗 If a sequence of n insert, combine, delete
min, delete, and decrease keyoperations is performed on an
initially empty F-heap, then we can amortize costs such that
the amortized time complexity of each insert, combine, and
decrease key operation is O(1) and that of each delete min
and delete is O(log n). The total time complexity of the entire
sequence is the sum of the amortized complexities of the
individual operations in the sequence
S ~ F-hearp
1) determine i is min distance and add i to S
~~ a delete min operation on S
2) distance value of the remaining vertices in S
~~ a decrease key operation on each of the affected
verties
total time (graph ) -- Ω ( n )
2
231
Chapter 7 SORTING
7.1 searching and list verification
a collection of information concerning some set about objects :
list ~ be stored within the available memory
file ~ be stored externally
record --- the information for one of the objects
field --- a smaller information unit within each record
key --- some field that server to identify the record
int i;
list [ n ] = searchnum;
for (i=0; list [ i] != searchnum; i++)
;
return ((i < n) ? i : - 1);
}
complexity
the average number of comparisons for a successful search:
n−1
∑ ( i + 1) / n = ( n + 1) / 2
i =0
program O( logn )
[5]
46
[2] [8]
17 58
[0] [10]
[3] [6]
4 26 48 90
[1] [4] [7] [9] [11]
15 30 56 82 95
157
(3) List verification
program1 O( mn )
158
program2 O(max [n log n, m log m ] )
void verify2( element list1[ ], element list2[ ], int n, int m)
/* same task as verify1,but list1 and list2 are sorted */
{ int i,j;
sort(list1, n); sort(list2, m);
i = j = 0;
while (i < n && j < m)
if ( list1[ i ].key < list2 [ j ].key){
printf("%d is not in list2\n", list1[i].key);
i++;
}
else if (list1[i].key == list2[j].key){
/* compare list1[i] and list2[j] on each of the other
fields and report any discrepancies */
i++; j++;
}
else {
printf("%d is not in list1\n",list2[j].key);
j++;
}
for ( ; i < n; i++)
printf("&d is not in list2\n", list1[i].key);
for ( ; j < m; j++)
printf("&d is not in list1\n", list2[j].key);
}
7.2 definitions
applications of sorting:
1. as an aid to searching
2. for matching entries in the lists
3. finding a permutation (permutation is not unique)
159
(2) | stable | if i < j and Ki = kj in the input
list, then Ri precedes R j in the sorted
list
sorting methods:
internal sort ---- the list is small enough to sort entries
in main memory
selection sort insertion sort quick sort
heap sort merge sort radix sort
external sort ---- there is too much information to fit into
main memory
7.3 insertion sort
program
void insertion_sort(element list[ ],int n)
/* perform a insert sort on the list */
{
int i, j;
element next;
for (i = 1; i < n; i++){
next = list[ i ];
for (j = i-1; j >= 0 && next.key < list[j].key; j--)
list[ j+1] = list [ j ];
list [ j+1] = next;
}
}
n−1
complexity Ο ( ∑ i ) = Ο ( n2 )
i =0
left out of order ( LOO ) Ri is LOO iff Ri < max
0≤ j < i
{ Rj }
if K is the number of records LOO,
then the computing time O((k+1)n ).
worst case: Ο( n )
2
case: Ο( n )
2
average
〖example〗 n = 5, input ( 5, 4, 3, 2, 1)
i [0] [1] [2] [3] [4]
- 5 4 3 2 1
1 4 5 3 2 1
2 3 4 5 2 1
160
3 2 3 4 5 1
4 1 2 3 4 5
〖example〗 n = 5, input ( 2, 3, 4, 5, 1)
Quick sort differs from insertion sort in that the pivot key Ki
controlling the process is placed at the right spot with respect
to the whole file.
1. if key Ki placed in position S(i),
then K j <= K s( i ) for j < S(i)
K j >= K s( i ) for j > S(i)
2. original file is partitioned into two subfiles:
R0, …, R s(i) -1 ( left of s(i) )
R s(i) +1, … ,R n -1 ( right of s(i) )
3. sort these subfiles
161
program quicksort ( list, 0, n-1 )
do
j--;
while (list[ j ], key > pivot);
if (i < j)
SWAP(list [ i ], list [ j ], temp);
} while ( i < j);
SWAP(list [ left ], list[ j ], temp);
quicksort( list, left, j-1);
quicksort( list, j+1, right);
}
}
〖example〗 n =10 input (26, 5, 37, 1, 61, 11, 59, 15, 48, 19)
R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
left right
[26 5 37 1 61 11 59 15 48 19]
0 9
[11 5 19 1 15] 26 [59 61 48 37]
0 4
162
[1 5] 11 [19 15] 26 [59 61 48 37]
0 1
1 5 11 [19 15] 26 [59 61 48 37]
3 4
1 5 11 15 19 26 [59 61 48 37]
6 9
1 5 11 15 19 26 [48 37] 59 [61]
6 7
1 5 11 19 15 26 37 48 59 [61]
9 9
1 5 11 19 15 26 37 48 59 61
worst case : O( n
2
)
best case : O(n)
average case:
T (n) -- the time taken to sort a file of n records:
T(n) ≤ cn + 2T(n/2), for some constant c
≤ cn + 2(cn/2 + 2T(n/4))
≤ 2cn + 4T(n/4)
·
≤ cn log 2 n + nT(1) = O(n log 2 n )
163
Tavg ( m ) ≤ cm +
4b 2k m
+ z
x log e xdx = cm +
4 b 2 k m 2 log e m m 2
+ −
L
M O
P
m m 2 m m 2 4 N Q
4b km
= cm + + km log e m − ≤ km log e m for m >= 2
m 2
stack space: O(log n)
variation
quicksort using a median of three:
povit = median { K left , K ( left + right )/ 2 ) , K right }
K0<=K1 [0,1,2]
YES NO
[0,1,2] [1,0,2]
K1<=K2 K0<=K2
NO
YES NO YES NO
[0,1,2]
[0,2,1] [1,0,2] [1,2,0]
stop K0<=K2 stop K1<=K2
I YES NO IV YES NO
[2,0,1] [1,2,0] [2,1,0]
[0,2,1] stop stop stop stop
II III V VI
164
【corollary】any algorithm that sort by comparison only must
have a worst computing time of Ω( n log 2 n )
proof:
for every decision tree with n! leaves there is a path of length
c n log 2 n , c a constant, By the theorem, there is path length
log 2 n!
n/ 2
n! = n(n-1)(n-2), ..., (3) (2) (1) >= ( n / 2 )
so, log 2 n! >= (n/2) log 2 ( n / 2 ) = O( n log 2 n )
(1) merging
algorithm1
void merge(element list[ ],element sorted[ ],int i,int m, int n)
/* merge two sorted files: list[i], ..., list[m], and list[m+1], ...,
list[n]. These files are sorted to obtain a sorted list :
sorted [i] , ..., sorted[n] */
{
int j, k, t;
j = m+1; /* index for the second sublist */
k = i; /* index for the sorted list */
complexity
165
computing time: O( n - i + 1)
m - the length of a record O( m( n - i + 1))
steps:
1. Identify the n records with largest keys. This is done by
following right to left along the two files to be merged.
2. Exchanged the records of the second file that were
identified step 1 with those just to the left of those
identified from the first file so that the n records with
largest keys form a contiguous block.
3. swap the block of n largest records with the leftmost
block ( unless it is already the leftmost block ). Sort the
rightmost block.
4. Reorder the blocks excluding the block of largest records
into nondecresing order of the last key in the blocks.
5. perform as many merge sub steps as needed to merge
the n - 1 blocks other than the block with the largest keys
6. sort the block with the largest keys.
0 2 4 6 8 a c e g i j k l m n t w z 1 3 5 7 9 b d f h o p q r s u v x y
0 2 4 6 8 a c e g i j k l m n t w z 1 3 5 7 9 b d f h o p q r s u v x y
0 2 4 6 8 a c e g i j k u v x y w z 1 3 5 7 9 b d f h o p q r s l m n t
u v x y w z c e g i j k 0 2 4 6 8 a 1 3 5 7 9 b d f h o p q l m n r s t
. . .
u v x y w z 0 2 4 6 8 a 1 3 5 7 9 b c e g i j k d f h o p q l m n r s t
. . .
0 v x y w z u 2 4 6 8 a 1 3 5 7 9 b c e g i j k d f h o p q l m n r s t
. . .
0 1 x y w z u 2 4 6 8 a v 3 5 7 9 b c e g i j k d f h o p q l m n r s t
. . .
0 1 2 y w z u x 4 6 8 a v 3 5 7 9 b c e g i j k d f h o p q l m n r s t
166
. . .
0 1 2 3 4 5 u x w 6 8 a v y x 7 9 b c e g i j k d f h o p q l m n r s t
. .
0 1 2 3 4 5 6 7 8 u w a.v y z x 9 b c e g i j k d f h o p q l m n r s t
.. .
0 1 2 3 4 5 6 7 8 9 a w v y z x u b c e g i j k d f h o p q l m n r s t
. . .
0 1 2 3 4 5 6 7 8 9 a w v y z x u b c e g i j k d f h o p q l m n r s t
. . .
0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k v z u y x w o p q l m n r s t
. . .
0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k v z u y x w o p q l m n r s t
. . .
0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q y x w v z u r s t
.
0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t v z u y x w
complexity
step1, step2 (each ): space O(1) time O( n )
step3: swapping : space O(1) time O( n )
sort (insertion sort) : time O( n ) space O(1)
step4: selection sort: time O( n ) space O(1)
1.5
insertion sort: time O( n )
step5: time O( n )
step6 ( any sort): time O( n )
total time : O( n ), space : O(1)
167
void merge_sort(element list[ ], int n)
/* perform a merge sort on the files */
{ int length = 1;/* current length being merged */
element extra[MAX_SIZE];
while(length > n){
merge_pass(list, extra, n, length);
length *= 2;
merge_pass(extra, list, n, length);
length *= 2;
}
}
〖example〗input ( 26, 5, 77, 1, 61, 11, 59, 15, 48, 19 )
26 5 77 1 61 11 59 15 48 19
5 26 1 17 11 61 15 59 19 48
1 5 26 77 11 15 59 61 19 48
1 5 11 15 26 59 61 77 19 48
1 5 11 15 19 26 48 59 61 77
typedef struct {
int key:
/* other field */
int link;
} element;
168
rmerge (list, middle + 1, upper));
}
}
26 5 77 1 61 11 59 15 48 19
5 26 15 59
5 26 77 1 61 11 15 59 19 48
1 5 26 61 77 11 15 19 48 59
1 5 11 15 19 26 48 59 61 77
i R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
key 26 5 77 1 61 11 59 15 48 19
link 8 5 -1 1 2 7 4 9 6 0
169
return list[n].link;/* start of the new list */
}
〖example〗input ( 26, 5, 77, 1, 61, 11, 59, 15, 48, 19 )
variation
natural merge sort: prevailing order within the input list
26 5 77 1 61 11 59 15 48 19
5 26 77 1 11 59 61 15 19 48
1 5 11 26 59 61 77 15 19 48
1 5 11 15 19 26 48 59 61 77
max child */
break;
else{
170
list[child/2] = list[child]; /* move to parent
*/
child *= 2;
}
}
list [child/2] = temp;
}
complexity
suppose: 2 ≤ n < 2
k −1 k
171
[1]
26
[2] [3]
5 7
7
[7]
[4] [5] [6]
1 61 11 59
[8] [9]
15 48 19 [10]
2. max heap
[1] [1]
77 61
[2] [3] [2] [3]
61 59 48 59
[7] [7]
[4] [5] [6] [4] [5] [6]
48 19 11 26 15 19 11 26
[1] [1]
59 48
[1]
26
[2] [3]
19 11
[7]
[4] [5] [6]
15 5 1 48
[8] [9]
59 61 77 [10]
172
K0 ---- the most significant key
r−1
K ---- the least significant key
j j
Ki ---- the key K of record Ri
A list of records, R0 , R1 , ...., Rn−1 is lexically sorted with
0 1 r −1
respect to the keys K , K , ...., K iff
( K i , K i , ..., K i ) ≤ ( K i +1 , K i +1 , ..., K i +1 )
0 1 r −1 0 1 r −1
0 ≤ i < n-1
□ r-tuple ( x0, x1, …, xr-1 ) ≤ r-tuple ( y0, y1, …, yr-1 )
iff
either xi = yi , 0 ≤ i ≤ j and xj+1 < yj+1 for some j < r-1
or xi = yi , 0 ≤ i < r
〖example〗
K 0 [suit]:
K 1 [face value]: 2 < 3 < 5 < … < 10 < J < Q < K < A
2 , ... , A , ... , 2 , ... , A
a sorted deck of cards:
3 5 4 A
2 3 4 A
173
int key[MAX_DIGIT];
list_pointer link;
};
〖example〗
initial input :
174
179-> 208-> 306-> 93-> 859-> 984-> 55-> 9-> 271-> 33
first pass , i = 2:
271-> 93 -> 33 -> 984 -> 55 -> 306 -> 208 -> 179 -> 859 -> 9
175
front[0] 9 33 55 93 null
rear[0]
front[1] 179 null rear[1]
front[2] 208 271 null rear[2]
front[3] 306 null rear[3]
front[4] null rear[4]
front[5] null rear[5]
front[6] null rear[6]
front[7] null rear[7]
front[8] 859 null rear[8]
front[9] 984 null rear[9]
third pass i = 0:
9 -> 33 -> 55 -> 93 -> 179 -> 208 -> 271-> 306 -> 859 -> 984
The sort does not physically rearrange the list, but modifies the
link field to show the sorted order.
three methods:
1, 2 ~ require linked list representations
3 ~ an auxiliary table that indirectly references the
list's records.
typedef struct {
176
int key;
int link;
int linkb; /* back link */
} element:
last = -1;
for (current = start; current != -1;
current =
list[current].link)
{
/* establish the back links for the list */
list[current].linkb = last;
last = current;
}
for (i = 0; i < n-1; i++){
/*move list[start] to position i while maintaining the list
*/
if (start != i){
if (list [ i ].link+1)
list [list [ i ].link].linkb = start;
list [ list[ i ].linkb].link = start;
SWAP ( list[start], list[i], temp);
}
start = list[i].link;
}
}
complexity O( mn )
n --- the number of records in the list
m --- each record is m words long
177
〖example〗input list ( 26, 5, 77, 1, 61, 11, 59, 15, 48, 19 )
start = 3 (linked list )
i R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
key 26 5 77 1 61 11 59 15 48 19
link 8 5 -1 1 2 7 4 9 6 0
linkb
i=2 start = 5
i R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
key 1 5 77 26 61 11 59 15 48 19
link 1 5 -1 8 2 7 4 9 6 3
linkb -1 3 4 9 6 1 8 5 3 7
i=3 start = 7
i R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
key 1 5 11 26 61 77 59 15 48 19
link 1 5 7 8 5 -1 4 9 6 3
linkb -1 3 1 9 6 4 8 5 3 7
i=4 start = 9
i R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
key 1 5 11 15 61 77 59 26 48 19
link 1 5 7 9 5 -1 4 9 8 7
linkb -1 3 1 5 6 4 8 5 9 7
178
void list_sort2(element list[ ], int n, int start)
/* list sort with only one link field */
{ int i, next;
element temp;
for (i = 0; i < n-1; i++){
while(start < i) start = list[start].link;
next = list[start].link; /*save index of next largest
key*/
if (start != i){
SWAP(list[i], list[start], temp);
list[i].link = start;
}
start = next;
}
}
complexity O( mn )
179
i=4 start = 0
i R0 R1 R2 R3 R4 R5 R6 R7 R8 R9
key 1 5 11 15 19 77 59 26 48 61
link 3 5 5 7 9 -1 4 8 6 2
□list sort is not well suited for quick sort or heap sort.
before 0 1 4 Auxiliary
sort 2 3
table T
R0 R1 R2 R3 R4
key 50 9 11 8 3
After Auxiliary
4 3 1 2 0
sort table T
void table_sort(element list[ ], int n, int table[ ])
/* rearrange list[0], .., list[n-1] to correspond to the
sequence list[table[0]], ..., list[table[n-1]] */
{ int i, current, next;
element temp;
for (i = 0; i < n-1; i++)
if (table[i] != i){
/* nontrivial cycle starting at i */
temp = list[i]; current = i;
do {
next = table[current];
list[current] = list[next];
table[current] = current;
current = next;
}while(table[current] != i);
list[current] = temp;
table[current] = current;
}
}
〖example〗
initial configuration:
180
i R0 R1 R2 R3 R4 R5 R6 R7
key 35 14 12 42 26 50 31 18
table 2 1 7 4 6 0 3 5
insertion sort
advantage: low overhead
suited case: already partially ordered
small n
merge sort
advantage: best worst case behavior
shortcoming: more storage
suited case: large n
quick sort
advantage: best average behavior
shortcoming: worst case behavior is O( n )
2
radix sort
shortcoming: behavior depends on the size of the key and
the choice of the radix
181
2
quick O( n log n) --> O( n) <--> O( n )
2
select& straight O( n )
2
tree binary tree O( n log n) skewedO( n )
tournament O( n log n) 2 n +1 number
heap O( n log n) small n
2 2
insertion simple O( n ) -->O( n) <-- O( n )
2
shell O( n(log n ) )
2
address O( n ) n/m=1O( n) n/m>>1O( n2 )
merge & merge O( n log n) large n small n
radix radix O( m * n) small m large m
〖example〗
file -- 4500 records (A1, …, A4500 )
block -- 250 records
run -- 3 blocks
1. internally sort three blocks at a time (i.e. 750 records ) to
obtain six runs R1 - R6
run1 run2 run3 run4 run5 run6
182
run1 run2 run3 run4 run5 run6
750records 750records 750records 750records 750records 750records
operation
time
(1) read 18 blocks of input , 18tIO , 36 tIO + 6tIS
internally sort, 6tIS ,
write 18 blocks, 18tIO
(2) merge runs 1-6 in pairs 36 tIO + 4500
tm
(3) merge two runs of 1500 records 24tIO + 3000 tm
each , 12 blocks
(4) merge one run of 3000 records 36 tIO+ 4500 tm
with one run of 1500 records
___________________
total time
132tIO + 12000 tm + 6tIS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
183
k-way merge
1 2 ...k k+1 ... 2k ([m/k]-1)k+1 ...m
[log km]+1levels
n records-->m runs
---> [ log k m ] + 1 level
--> k-way merge
--> merge log k m passes
merge k-runs ( s1,s2,s3,, …,sk ) --> O((k-1) ∑1 si )
k
computing time
total computing time : n(k-1) log k m computing number
n(k-1) log k m = n(k-1) log 2 m / log 2 k = n log 2 m * (k-1) /
log 2 k
184
〖example〗run 1 : 1,3,5,7,8,9 run 2 : 2,4,6,15,20,25
- - 1 3
- - 2 4
ou[1] ou[2]
output ou[1]
merge into ou[1] merge into ou[2]
1 2 - - - -
3- 4 input into in[3] 3 4 input into in[4]
- -
in[1] in[2]
- - 5 5 6
- - 7 7 15
in[3] in[4]
5 7 9
6 8 -
- - - - -
7 15 - 15 15
assumption about the parallel processing capabilities:
(1) two disk drives and the input/output channel
(2) while data transmission is taking place between an
input/output device and a block of memory, the
CPU
cannot make references to that same block of the
memory.
(3) input and output buffer are to be the same size.
buffering algorithm
step 2: let lastkey [i] be the last key input from run i. let
nextrun be the run for which lastkey is minimum.if
lastkey [nextrun] < > + then initiate the input
of the next block from run nextrun.
185
step 3: use a function kwaymerge to merge records from the
k input queues into the output buffer ou. merging
continues until either the output buffer gets full or
arecord with key + is merged into ou. if,
during this merge , an input buffer becomes
empty before the output buffer gets full or
before a + is merged into a ou, the
kwaymerge advances to the next bufferon the
same queue and returns the empty buffer to the
stack of empty buffers.However , if an input
buffer becomes empty at the same time as the
output buffer gets full or + is merged into ou,
the empty buffer is left on the queue and
kwaymerge does not advance to the next buffer
on the queue.
Rather, the merge terminate.
step 4: wait for any ongoing disk input/output to complete.
step 5: if an input buffer has been read, add it to the queue
for the appropriate run. Determine the next run to
read from by determining nextrun such that
lastkey[nextrun] is minimum.
step 6: if lastkey [nextrun] + , then initiate reading
the next block from run nextrun into a free
input buffer.
step 7: initiate the writing of output buffer ou. Set ou = 1- ou.
step 8: if a record with key + has not been merged into
the output buffer go back to step 3.Otherwise, wait
for the ongoing write to complete and then terminate.
〖example〗
run1 20 25 26 28 29 30 33 +
run2 23 29 34 36 38 60 70 +
run3 24 28 31 33 40 43 50 +
186
next block
line queue run2 run3 outpu
run1 being read from
1 20 25 23 29 24 28 no output run1
2 25 26 28 29 24 28 20 23 run1
3 26 28 29 30 29 28 24 25 run3
4 29 30 29 28 31 33 26 28 run2
5 29 34 36 28 29
30 31 33 run1
6 33 + 34 36 31 33 29 30
run3
7 + 34 36 33 40 43 31 33 run2
8 + 36 38 60 40 43 33 34 run3
9 + 60 40 43 50 + 36 38 run2
10 + 60 70 + 50 + 40 43 no next
11 + 70 + + 50 60 no next
12 + + 70 +
187
tree[i].data.run run number to which tree[i].data
belong
tree[i].loser loser of the tournament played at node
i
current_run run number of current run
winner position of overall tournament
winner,[0]
winner_run run number for tree[winner].data
max_runs number of runs that will be generated
last_key key value of last record output
in = open_input(in_name);
out = fopen(out_name, "wb");
for (i = 1; i < k; i++){
/* set up tree with dummy nodes */
tree[i].data.key = 0;
tree[i].data.run = 0;
tree[i].loser = i;
}
tree[winner].data.run = 0;
for ( ; ; ){
if (winner_run != current_run){
if (winner_run > max_runs){
/* last record reached , close files and return
*/
fclose(in); fclose(out);
return;
}
current_run = winner_run;
188
}
if (winner_run){
/* suppress output if dummy records */
fwrite(&tree[winner].data, sizeof(element), 1,
out);
last_key = tree[winner].data.key;
}
fread(&tree[winner].data, sizeof(element), 1,
in);
if (feof(in)){ /* signal to end
processing */
winner_run = max_runs+1;
tree[winner].data.run = winner_run;
}
else {
if (tree[winner].data.key < last_key){
winner_run++;
tree[winner].data.run = winner_run;
max_runs = winner_run;
}
else
tree[winner].data.run = current_run;
}
/* adjust tree */
parent = (k + winner)/2;
while(parent){
loser = tree[parent].loser;
if (tree[loser].data.run < winner_run ||
(tree[loser].data.run == winner_run &&
tree[loser].data.key <
tree[winner].data.key)){
temp = winner;
winner = tree[parent].loser;
tree[parent].loser = temp;
winner_run = tree[winner].data.run;
}
parent/ = 2;
}
}
189
}
intrenal node
15
and
5
2 4 5 15
2 4 extrenal node
Huffman tree
a binary tree with minimum weighted external path length
190
tree_pointer tree;
int n;
191
5 10 16
2 3 5 5 7 9
2 3
39
23
16 23
10 13 10
7 9 13
5 5 5 5
2 3 2 3
192
chapter 9 heap structures
9.1 Min-Max heap
7 min
70 40 max
30 9 10 15 min
45 50 30 20 12 max
212
if (item.key > heap[grandparent].key) {
heap[i] = heap[grandparent];
i = grandparent;
grandparent /= 4;
}
else
break;
heap[i] = item;
}
7 min
70 40 max
30 9 10 15 min
45 50 30 20 12 j max
inserting 5
5 min
70 40 max
30 9 7 15 min
45 50 30 20 12 10 max
inserting 80
7 min
70 80 max
30 9 10 15 min
45 50 30 20 12 40 max
213
(2) deletion of min element
12 min
70 40 max
30 9 10 15 min
45 50 30 20 max
9 min
70 40 max
30 12 10 15 min
45 50 30 20 max
214
element delete_min(element heap[ ], int *n)
{ /* delete the minimum element from the min-max heap:
O(log n) */
int i, last, k, parent;
element temp, x;
if ( !(*n) ) {
fprintf(stderr,"The heap is empty\n");
heap[0].key = INT_MAX; /* error key in heap[0] */
return heap[0];
}
heap[0] = heap[1]; /* save the element */
x = heap[ (*n)-- ];
/* find place to insert x */
for ( i = 1, last = (*n)/2; i <= last;) {
k = min_child_grandchild(i, *n);
if (x.key <= heap[k].key) break;
/* case 2(b) or 2(c) */
heap[i] = heap[k];
if (k <= 2*i+1) { /* 2(b) */
i = k;
break;
}
/* case 2(c), k is a grandchild of i */
parent = k/2;
if (x.key > heap[parent].key)
SWAP(heap[parent],x,temp);
i = k;
} /* for */
heap[i] = x;
return heap[0];
}
215
9.2 deaps
if ( j > n ) j /= 2
5 45
10 8 25 40
15 19 9 30 20
216
5 45
10 8 25 40
15 19 9 30 20
i j
insertion of 4
4 45
5 8 25 40
15 10 9 30 20 19
insertion of 30
5 45
10 8 30 40
15 19 9 30 20 25
functions
• max_heap ( n )
this function return TRUE iff n is a position in the
max-heap of the deap.
• min_partner ( n )
This function compute the min_heap node that
corresponds to the max-heap position n. This is given by
[log n]−1
n- 2 2
• max_partner ( n )
217
This function compute the max-heap node that
corresponds to the parent of min-heap position n. This is
[log n]−1
given by ( n - 2 2
)/2
218
else
max_insert(deap,*n,x);
}
}
8 45
10 9 25 40
15 19 20 30
219
j = i*2;
if (j+1 < = *n) {
if (deap[j].key > deap[j+1].key)
j++;
}
}
modified_deap_insert(deap , i , temp);
return deap[0];
}
A G
B C H I
D E F J
2 2
A G
2 1 1 1
B C H I
1 1 1
D E F J
shortest ( x ) =
R
So if x is an external node
T1+ min{ shortest ( left _ child ( x )), shortest ( right _ child ( x ))} otehrwise
【definition】
A leftist tree is a binary tree such that iff it is not empty,
then
shortest (left_child(x)) >= shortest(right_child(x))
220
for every internal node x
〖Lemma9.1〗
Let x be the root of a leftist tree that has n (internal ) nodes.
(a) n >= 2
shortest ( x )
-1
(b) The rightmost root to external node path is the shortest
root to external node path. Its length is shortest( x ).
typedef struct {
int key;
/* other field */
} element;
typedef struct leftist *leftist_tree;
struct leftist {
leftist_tree left_child;
element data;
leftist_tree right_child;
int shortest;
};
【definition】 A min-leftist tree (max leftist tree) is a leftist tree
in which the key value in each node is no large ( smaller ) than
the key value in its children ( if any ). In other words. a min (max)
leftist tree is a leftist that is also a min ( max ) tree
2 2
2 a 5 b
1 1 1 1
7 50 9 8
1 1 2 1
11 80 12 10
1 1 1 1
13 20 18 15
221
delete the min element <-- a
• combine a->left_child and a->right_child
• delete node a
combine a and b
• obtain a new binary tree containing all elements in a
and b following the rightmost path in a and/or b. (the key in
each node is no larger than the key in its children )
• interchange the left and right subtree of nodes as
necessary to convert this binary tree into a leftist tree
2
5
2 2
8 1
1 1 9 8
2 1 1
10 50
1 1 12 10 50
1 1 1 1
15 80
20 18 15 80
2 2
2 2
1 2 1
7 5 5 71
1 1 2 2 1
11 9 8 8 9 11 1
1 1 1
2 1 1 2
13 12
1
10 50
1
10 50 12 13 1
1 1 1 1 1 1
20 18 15 80 15 80 20 18
222
else if (*b)
min_union(a , b);
*b = NULL;
}
individual operation:
binomial heap ~ O ( n )
223
leftist tree ~ O ( log n )
amortize part of the cost of expensive operation over the
inexpensive once ~ O ( 1 ) or O ( log n )
amortize scheme :
charge some of the actual cost of an operation to other
operations. This reduce the charged cost of some operations
and increases that of others
〖example〗
operation sequence: I1,I2,D1,I3,I4,I5,I6,D2,I7
actual cost: I1 ~ I7 -- 1, D1 - 8, D2 -- 10 ( unit of
time )
total cost = 25
if 2 units (D1) --> I1, I2, 4 units ( D2) --> I2 ~ I6
the amortized cost of each of I1 ~ I6 = 2 units
the amortized cost of each of D1 ~ C2 = 6 units
the total amortized cost = (2*6+1*+2*6 ) = 25 units
224
1
3
8 12 7 16
5 4
10 15 30 9
6
20
insert, combine -- O (1) (actual , amortized time )
delete -- O ( log n ) ( amortized time )
B-heap representation : doubly linked list
field: degree, child, left_link, right_link, data
a
8 3 1
5 4 12 7 16
10
6 15 30 9
20
(3) insertion into a binomial heap O (1)
element x --> B-heap a
1. putting x into a new node
2. placing this node into the doubly linked circular list
pointer at by a
3. if a is null or x's key < the key in the node pointed by a
then reset a to the new node
225
linked circular list; Now, a pointer to any
remaining
node in the resulting list; If there is no such
node,
then a = NULL
step3: [Min-tree joining]
Consider the min-tree in the list a and y; joining
together pairs of min-tree of the same degree
until
all remaining min-trees has different degree;
step4: [Form min-tree root list]
Link the roots of the remaining min-tree ( if any )
together to form a doubly linked circular list;
Set a
to point the root ( if any ) with minimum key;
new
B-heap consist of the remaining min-tree and
the
sub min-tree of the deleted root
8 3 12 7 16
5 4 15 30 9
10
6 20
making the min-tree whose root has larger key a subtree of the other
7 3 12 16
8 9 5 4 15 30
6 20
10
226
3 12 16
7 5 4
15 30
8 9 6
20
10
(6) analysis
227
Fibonacci heap:
min-Fibonacci heap is a collection of min-tree ( F-heap )
max-Fibonacci heap is a collection of max-tree
operations:
the deletion of 12
228
8 3 1 15 30
5 4 7 16 20
10
6 9
the reducetion of 15 by 4
8 3 1 11
5 4 7 16 20
12
10
6 30 9
229
□each time two min-tree are joined in a delete min
operation, the child_cut of the root with larger key = False
2
14 12 10
F
4 5
16 15
T 18 30 11
6 60
T
20 8 7
8 6
T
10
20 7
T
30 12 11
2
*
14 18 4 5
16 15 60
(4) Analysis
〖Lemma9.3〗 Let a be an F-heap with n elements that
results from a sequence of insert, combine, delete min, delete,
and decrease key operations performed on initially empty F-
heap
(a) Let b be any node node in any of the min-trees of a.
The degree of b is at most log φ m , where
φ = ( 1+ and m is the number of elements in the
5 ) / 2
subtree with root b.
(b) MAX_DEGREE ≤ [ log φ m ] and the actual cost of a delete
230
min is O(log n + s)
〖Theorem9.2〗 If a sequence of n insert, combine, delete
min, delete, and decrease keyoperations is performed on an
initially empty F-heap, then we can amortize costs such that
the amortized time complexity of each insert, combine, and
decrease key operation is O(1) and that of each delete min
and delete is O(log n). The total time complexity of the entire
sequence is the sum of the amortized complexities of the
individual operations in the sequence
S ~ F-hearp
1) determine i is min distance and add i to S
~~ a delete min operation on S
2) distance value of the remaining vertices in S
~~ a decrease key operation on each of the affected
verties
total time (graph ) -- Ω ( n )
2
231