A historian wants to classify a set of events. Each event is characterized by a $$\textit{title}$$, a $$\textit{location}$$ and a $$\textit{period}$$ of time (as most of the events are spread over several years). $$\textit{Title}$$ and $$\textit{location}$$ are strings, while the $$\textit{period}$$ is a closed interval $$[start,end]$$, where $$start$$ and $$end$$ is a pair of integers such that $$-\infty < start \leq end <+\infty$$.
In the following, we use the following declarations:
typedef struct {int start, end;} interval;
typedef struct {
char *title, *location;
interval period;} Event;
Here are some examples of events:
$$\begin{array}{|c|c|c|}
\hline \textbf{Title} & \textbf{Location} & \textbf{Period} \\
\hline \text{World War II} & world & [1939-1945] \\
\hline \text{First Atomic Bomb} & Hiroshima & [1945-1945] \\
\hline \text{JFK president} & USA & [1961-1963] \\
\hline \text{Independence} & Lebanon & [1943-1943] \\
\hline\end{array}$$
Note that certain events are spread over several years, while others begin and end the same year.
In order to classify these events, the historian builds a binary tree of events ($$\texttt{BtreeE}$$) whose data are events such as:
- If $$EvL$$ is in the left subtree of $$Ev$$, then $$EvL.start \leq Ev.start$$
- If $$EvR$$ is in the right subtree of $$Ev$$, then $$EvR.start > Ev.start$$
Thus, an event tree is a binary search tree for the event starting year in which repetitions can occur since $$\textbf{EvL.start} \leq \texttt{Ev.start}$$ (see figure below, where T$$_i$$ denotes a $$\textit{title}$$ and L$$_i$$ a $$\textit{location}$$). We therefore have the following declaration:
typedef struct node {
Event data;
struct node *Left, *Right;} *BtreeE;
- Write a recursive function $$\texttt{int contains(BtreeE B, int year)}$$ that returns the number of events of $$B$$ such as $$year$$ $$\in$$ interval of these events.
- Write an iterative function that returns the minimum interval that contains all the intervals of events of a given $$\texttt{BtreeE}$$.
In the previous example, the result will be $$[1210, 1985]$$. - Write a function $$\texttt{int isBtreeE(BtreeE B)}$$ that determines whether a given event tree $$\texttt{B}$$ satisfies the properties of a $$\texttt{BtreeE}$$.
- Write a function $$\texttt{int LongestInterval(BtreeE B, Event E)}$$ that returns the time in years from the largest inersection event between $$E$$ and those of $$B$$.
Example: the intersection of the event T8, L8, [1923-1960] with the previous tree is 31; it comes from the intersection with T2, L2, [1870-1954]. - Write a function $$\texttt{int maxLong(BtreeE B)}$$ that returns the longest common period (intersection) of two events in a given $$\texttt{BtreeE}$$.
In the previous tree, the events, T2,L2,[1870-1954] and T5,L5,[1930-1985] have an intersection of 24 years (between 1930 and 1954).
Difficulty level
Video recording
This exercise is mostly suitable for students
int contains (Btree B, int year)
{
if(B==NULL)
return 0;
if( year >= B->data.period.start && year <= B->data.period.end )
return 1+ contains (B->left,year)+contains (B->right,year);
return contains (B->left,year)+contains (B->right,year);
}
int contains2(Btree B, interval *v)
{
element e;
int min = INT_MAX;
int max = INT_MIN;
if(B)
{
queue q = CreateQueue();
EnQueue(&q,B);
while(Front(q,&e))
{
DeQueue(&q);
if(e->data.period.start<min)
min=e->data.period.start;
if(e->data.period.end>max)
max=e->data.period.end;
if(e->left)
EnQueue(&q,e->left);
if(e->right)
EnQueue(&q,e->right);
}
v->start=min;
v->end=max;
return 1;
}
return 0;
}
int FindMin(Btree tree)
{
int res;
int lres, rres;
if (tree == NULL) return INT_MAX;
res = tree->data.period.start;
lres = FindMin(tree->left);
rres = FindMin(tree->right);
if (lres < res) res = lres;
if (rres < res) res = rres;
return res;
}
int FindMax(Btree tree)
{
int res;
int lres, rres;
if (tree == NULL)
return INT_MIN;
res = tree->data.period.start;
lres = FindMax(tree->left);
rres = FindMax(tree->right);
if (lres > res) res = lres;
if (rres > res) res = rres;
return res;
}
int isBtreeE(Btree B)
{
if(B == NULL) return 1;
if(B->left != NULL && FindMax(B->left) > B->data.period.start) return 0;
if(B->right != NULL && FindMin(B->right) <= B->data.period.start) return 0;
if(!isBtreeE(B->left) || !isBtreeE(B->right)) return 0;
return 1;
}
int longestInterval(Btree B, Event E)
{
element e;
int interval = INT_MIN;
int lower_bound,upper_bound;
if(B)
{
queue q = CreateQueue();
EnQueue(&q,B);
while(Front(q,&e))
{
DeQueue(&q);
lower_bound=max(E.period.start,e->data.period.start);
upper_bound=min(E.period.end,e->data.period.end);
if(lower_bound<=upper_bound &&
upper_bound-lower_bound>interval &&
strcmp(e->data.title,E.title))
interval=upper_bound-lower_bound;
if(e->left)
EnQueue(&q,e->left);
if(e->right)
EnQueue(&q,e->right);
}
return interval;
}
return -1;
}
int maxLongr(Btree B, Btree tree)
{
int res, lres, rres;
if (tree == NULL) return INT_MIN;
res = longestInterval(B, tree->data);
lres = maxLongr(B,tree->left);
rres = maxLongr(B,tree->right);
if (lres > res) res = lres;
if (rres > res) res = rres;
return res;
}
int maxLong(Btree B)
{
return maxLongr(B,B );
}
Back to the list of exercises
Looking for a more challenging exercise, try this one !!
Removing a sequence of 3 characters from a string