Transcript lec13-oct23
Lecture 18
• Cell arrays (Ch 4), structures
• recursion (Ch 12)
Oct 24
Cell arrays
• suppose we want to represent a collection of
sets such as:
{1, 2, 4}, {3, 4, 6}, {7, 8}
• Each set can be represented by vector:
[1, 2, 4], [3, 4, 6], [7, 8]
• >> A = [[ 1, 2, 4], [3, 4, 6], [7, 8]]
A becomes [1, 2, 4, 3, 4, 6, 7, 8]
Cell arrays
Cell array – examples
Cell – operations
More about cell arrays and struct arrays
Cell Arrays
– Creating Cell Arrays
– Accessing Cell Arrays
– Using Cell Arrays
– Processing Cell Arrays
MATLAB Structures
– Constructing and Accessing One Structure
– Constructor Functions
Structure Arrays
– Constructing Structure Arrays
– Accessing Structure Elements
– Manipulating Structures
Concept: Collecting Dissimilar Objects
Heterogeneous collections permit objects of different data types to be
grouped in a collection.
– They allow data abstraction to apply to a much broader range of content.
– However, the fact that the contents of these collections may be of any data
type severely restricts the operations that can be performed on the collections
as a whole.
– Whereas a significant number of arithmetic and logical operations can be
performed on whole number arrays, algorithms that process heterogeneous
collections must deal with the data contents one item at a time.
Cell Arrays
• Cell arrays, as the name suggests, have the general form of arrays and can be
indexed numerically as arrays.
• However, each element of a cell array should be considered as a container in
which one data object of any class can be stored.
• They can be treated as arrays of containers for the purpose of concatenation
and slicing.
• However, if you wish to access or modify the contents of the containers, the
cells must be accessed individually.
Creating Cell Arrays
• By assigning values individually to a variable indexed with braces:
>> A{1} = 42
A = [42]
• By assigning containers individually to a variable indexed with brackets:
>> B[1] = {[4 6]};
B = [1x2 double]
• By concatenating cell contents using braces {. . .}:
>> C = {3, [1,2,3], 'abcde'}
C = [3] [1x3 double] 'abcde'
• By concatenating cell containers:
>> D = [A B C {'xyz'}]
D = [42] [1x2 double] [3] [1x3 double] 'abcde' 'xyz'
Accessing Cell Arrays
Continuing the previous examples, we have the following:
>> E = D(2) % parentheses - a container
E = [4 6]
However, braces are used to access the contents of the containers as follows:
>> D{2} % braces - the contents
ans = 4 6
If the right-hand side of an assignment statement results in multiple cell arrays,
the assignment must be to the same number of variables.
Using Cell Arrays
• Containing lists of possible values for switch/case statements
• Substituting for parameter lists in function calls
– For example, suppose you have a function largest(a, b, c) that
consumes three variables and produces the largest of the three values provided. It can
be used in the following styles:
A = 4;
B = 6;
C = 5;
N = largest(A, B, C)
params = { 4, 6, 5 };
N = largest(params{1:3})
Processing Cell Arrays
• Checking the class of the element can be achieved in one of two
ways:
– The function class(item) returns a string specifying
the item type that can be used in a switch statement.
– Individual test functions can be used in an if... elseif
construct;
– examples of the individual test functions are
isa(item, 'class'),
– iscell(...), ischar(...), islogical(...),
isnumeric(...), and
– isstruct(...)
MATLAB Structures
• Structures allow items in the collection to be indexed by field name.
• The data contained in a structure is referenced by field name, e.g.,
item1.
• The rules for making a field name are the same as those for a
variable.
• Fields of a structure, like the elements of a cell array, are
heterogeneous—they can contain any MATLAB object.
Constructing and Accessing a Structure
• To set the value of items in a structure A, the syntax is as
follows:
>> A.item1 = 'abcde'
A =
item1: 'abcde'
>> A.item2 = 42
A =
item1: 'abcde'
item2: 42
• Fields in a structure are accessed in the same way—by
using the dotted notation.
>> A.item2 = A.item2 ./ 2
A =
item1: 'abcde'
item2: 21
Manipulating Field Names
• To determine the names of the fields in a structure, the built-in function fieldnames(...)
returns a cell array containing the field names as strings.
>> names = fieldnames(A)
names =
'item1'
'item2’
• Fields can also be accessed “indirectly” by setting a variable to the name of the field, and then
using parentheses to indicate that the variable contents should be used as the field name:
>> fn = names{1};
>> A.(fn) = [A.(fn) 'fg']
A =
item1: 'abcdefg'
item2: 21
More about Field Names
• You can remove a field from a structure using the
built-in function rmfield(...).
• Be careful. rmfield(...) returns a new structure
with the requested field removed. It does not
remove that field from your original structure.
• If you want the field removed from the original, you
must assign the result from rmfield(...) to replace
the original structure:
>> A = rmfield(A, 'item1')
A =
item2: 21
Why Constructor Functions?
Use constructor functions, as opposed to “manually” entering data
into structures, for the following reasons:
– Manual entry can result in strange behavior due to typographical errors
or having fields in the wrong order
– The resulting code is generally more compact and easier to understand
– When constructing collections of structures, it enforces consistency
across the collections
Built-in Constructor Function struct(…)
>> struct('first','Fred', ...
'last','Jones', ...
'phone','(123) 555-1212', ...
'birth', struct( 'day', 31, ...
'month', 'February', ...
'year', 1965 ))
ans =
first: 'Fred'
last: 'Jones'
phone: '(123) 555-1212'
birth: [1x1 struct]
Custom Constructor Functions
• A typical custom constructor function
function ans = makeCD(gn, ar, ti, yr, st, pr)
% integrate CD data into a structure
ans.genre = gn ;
ans.artist = ar ;
ans.title = ti;
ans.year = yr;
ans.stars = st;
ans.price = pr;
• Usage:
>> CD = makeCD('Blues', 'Charles, Ray’,
'Genius Loves Company', 2004, 4.5, 15.35 )
CD =
genre: 'Blues'
artist: 'Charles, Ray'
title: 'Genius Loves Company'
year: 2004
stars: 4.5000
price: 15.3500
Building Structure Arrays Manually
>> entry(1).first = 'Fred';
>> entry(1).last = 'Jones';
>> entry(1).age = 37;
>> entry(1).phone = ' (123) 555-1212';
>> entry(2).first = 'Sally’;
>> entry(2).last = 'Smith’;
>> entry(2).age = 29;
>> entry(2).phone = '(000) 555-1212'
entry =
1x2 structure array with fields:
first
last
age
phone
Building Structure Arrays with struct(…)
genres = {'Blues', 'Classical', 'Country' };
artists = {'Clapton, Eric', 'Bocelli, Andrea', …
'Twain, Shania' };
years = { 2004, 2004, 2004 };
stars = { 2, 4.6, 3.9 };
prices = { 18.95, 14.89, 13.49 };
cds = struct( ‘genre’, genres, …
'artist', artists, …
'year', years, …
'stars', stars, …
'price', prices);
Building Structure Arrays with makeCD(…)
cds(1) = makeCD('Blues', 'Clapton, Eric', ...
'Sessions For Robert J', 2004, 2, 18.95 )
cds(2) = makeCD('Classical', ...
'Bocelli, Andrea', 'Andrea', 2004, 4.6, 14.89 )
cds(3) = makeCD( 'Country', 'Twain, Shania', ...
'Greatest Hits', 2004, 3.9, 13.49 )
cds(4) = makeCD( 'Latin', 'Trevi, Gloria', ...
'Como Nace El Universo', 2004, 5, 12.15 )
cds(5) = makeCD( 'Rock/Pop', 'Ludacris', ...
'The Red Light District', 2004, 4, 13.49 )
cds(6) = makeCD( 'R & B', '2Pac', ...
'Loyal To The Game', 2004, 3.9, 13.49 )
cds(7) = makeCD( 'Rap', 'Eminem', ...
'Encore', 2004, 3.5, 15.75 )
cds(8) = makeCD( 'Heavy Metal', 'Rammstein', ...
'Reise, Reise', 2004, 4.2, 12.65 )
Recursive functions
Before we conclude this chapter, we will discuss
recursive functions, those that can call themselves.
We have examples of functions that call other
functions, e.g. insertionsort calling insert etc.
If f(n) is defined in terms of f(n – 1), as for example, in the
case of factorial, why not let f call itself?
n! = n x (n – 1)!
Or in matlab:
fact(n) = n .* fact(n – 1)
Rules for recursive functions
1. there should be exit from recursion. (i.e., there
should be some conditional branch path in
which there is no recursive call). Such cases
are called the base cases.
2. recursive calls should make towards base case
(usually by calling itself with smaller input
values).
3. Recursion may be more time or memory
consuming so should be careful with their use.
Example 1: Write a recursive function to compute n!
function out = fact(n)
if n <= 1 out = 1;
else out = n .* fact(n-1);
end;
Example 2: Write a recursive function in Matlab to
perform binary search.
Assume array A is sorted in ascending order.
Search(A, low, high, x) will return the largest t
such that A(t) <= x.
Pre-condition: A(low) <= x <= A(high)
Thus low <= t <= high.
Initially, low = 1, high = size(A)
Recursive binary search program
function out = search(A, low, high, x)
% returns the largest t s.t. A(t) <= x where
low <= t <= high
% A is assumed to be sorted
if high - low == 1
if A(high) == x
out = high;
else
out = low;
end;
else
mid = floor((low + high)/2);
if A(mid) == x out = mid;
elseif A(mid) < x
out = search(A, mid + 1, high, x);
else out = search(A, low, mid - 1, x);
end;
end;
Binary search program
function out = binary_search(A, x)
if A(1) < x out = 0;
else
out = search(A, 1, length(A), x)
end
Project: Generating all subsets of a given
set
Given a set, like [1, 3, 4], the subsets are:
[ ]
[1]
[3]
[4]
[1 3]
[1 4]
[3 4]
[1 3 4]
We want to write a program to generate all the
subsets of a given collection
Idea behind algorithm – recursion
This is a problem for which non-recursive
solutions are significantly harder than recursive
solutions.
Idea: input array is a of length n.
Recursively find all subsets of a(2:n)
Then add a(1) to each of the subsets.
Combine the two collections.
Since we need to represent a collection of
sets, we have two choices:
1. use of cell arrays
2. use of two-dimensional arrays
The latter is not suitable for this problem since
the sizes of the subsets are not the same
We use recursion to generate the solution.
We need a function insert that inserts a given
number into all the sets of a given collection.
Example showing how insert works
Code for insert
function out = insert(i, lst)
% inserts i into each membet of lst
for j = 1:length(lst)
out{j}= [i, lst{j}];
end;
Code for subsets
function L = subsets(lst)
% generates all subsets of lst
if length(lst) == 0
L = {[]};
elseif length(lst) == 1
L = {[lst(1)],[]};
else
L1 = subsets(lst(2:end));
L2 = insert(lst(1), L1);
L = [L1, L2];
end;
Printing the contents of a cell array
function setprint(cellset)
% prints every member of the cell in one line
% assume cellset is a collection of sets of integers
for k=1:length(cellset)
aprint(cellset{k}); fprintf('\n');
end;
function aprint(r)
for j = 1:length(r)
fprintf('%d', r(j)); fprintf('
end;
fprintf('\n')
');
A recursive image tiling problem
Given an input image as in the left-side, we want to
produce the image on the right-side.
Solution to the recursive image tiling problem
Observation 1: 3rd
quadrant has the input
image, but shrunk into
quarter.
We need to write a
function shrink that
shrinks the image to
quarter size.
Quadrant 1 of the output is the shrunk version of the whole output.
Equivalently, if F is the function that outputs the image on the right when given
as input on the left, then F applied to the image on the 3rd quadrant of the
output is what goes into the 1st quadrant of the output.
Quadrants 2 and 4 are now easy to determine. They can be obtained by
copying a part of the image in quadrant 1.