Table of Contents for
Intermediate C Programming

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Intermediate C Programming by Yung-Hsiang Lu Published by CRC Press, 2015
  1. Front Cover
  2. Contents (1/2)
  3. Contents (2/2)
  4. List of Figures (1/2)
  5. List of Figures (2/2)
  6. List of Tables
  7. Foreword
  8. Preface
  9. Author, Reviewers, and Artist
  10. Rules in Software Development
  11. Source Code
  12. I. Computer Storage: Memory and File
  13. 1. Program Execution (1/2)
  14. 1. Program Execution (2/2)
  15. 2. Stack Memory (1/5)
  16. 2. Stack Memory (2/5)
  17. 2. Stack Memory (3/5)
  18. 2. Stack Memory (4/5)
  19. 2. Stack Memory (5/5)
  20. 3. Prevent, Detect, and Remove Bugs (1/2)
  21. 3. Prevent, Detect, and Remove Bugs (2/2)
  22. 4. Pointers (1/6)
  23. 4. Pointers (2/6)
  24. 4. Pointers (3/6)
  25. 4. Pointers (4/6)
  26. 4. Pointers (5/6)
  27. 4. Pointers (6/6)
  28. 5. Writing and Testing Programs (1/4)
  29. 5. Writing and Testing Programs (2/4)
  30. 5. Writing and Testing Programs (3/4)
  31. 5. Writing and Testing Programs (4/4)
  32. 6. Strings (1/3)
  33. 6. Strings (2/3)
  34. 6. Strings (3/3)
  35. 7. Programming Problems and Debugging (1/4)
  36. 7. Programming Problems and Debugging (2/4)
  37. 7. Programming Problems and Debugging (3/4)
  38. 7. Programming Problems and Debugging (4/4)
  39. 8. Heap Memory (1/3)
  40. 8. Heap Memory (2/3)
  41. 8. Heap Memory (3/3)
  42. 9. Programming Problems Using Heap Memory (1/4)
  43. 9. Programming Problems Using Heap Memory (2/4)
  44. 9. Programming Problems Using Heap Memory (3/4)
  45. 9. Programming Problems Using Heap Memory (4/4)
  46. 10. Reading and Writing Files (1/3)
  47. 10. Reading and Writing Files (2/3)
  48. 10. Reading and Writing Files (3/3)
  49. 11. Programming Problems Using File (1/2)
  50. 11. Programming Problems Using File (2/2)
  51. II. Recursion
  52. 12. Recursion (1/4)
  53. 12. Recursion (2/4)
  54. 12. Recursion (3/4)
  55. 12. Recursion (4/4)
  56. 13. Recursive C Functions (1/4)
  57. 13. Recursive C Functions (2/4)
  58. 13. Recursive C Functions (3/4)
  59. 13. Recursive C Functions (4/4)
  60. 14. Integer Partition (1/5)
  61. 14. Integer Partition (2/5)
  62. 14. Integer Partition (3/5)
  63. 14. Integer Partition (4/5)
  64. 14. Integer Partition (5/5)
  65. 15. Programming Problems Using Recursion (1/5)
  66. 15. Programming Problems Using Recursion (2/5)
  67. 15. Programming Problems Using Recursion (3/5)
  68. 15. Programming Problems Using Recursion (4/5)
  69. 15. Programming Problems Using Recursion (5/5)
  70. III. Structure
  71. 16. Programmer-Defined Data Types (1/6)
  72. 16. Programmer-Defined Data Types (2/6)
  73. 16. Programmer-Defined Data Types (3/6)
  74. 16. Programmer-Defined Data Types (4/6)
  75. 16. Programmer-Defined Data Types (5/6)
  76. 16. Programmer-Defined Data Types (6/6)
  77. 17. Programming Problems Using Structure (1/4)
  78. 17. Programming Problems Using Structure (2/4)
  79. 17. Programming Problems Using Structure (3/4)
  80. 17. Programming Problems Using Structure (4/4)
  81. 18. Linked Lists (1/3)
  82. 18. Linked Lists (2/3)
  83. 18. Linked Lists (3/3)
  84. 19. Programming Problems Using Linked List (1/2)
  85. 19. Programming Problems Using Linked List (2/2)
  86. 20. Binary Search Trees (1/4)
  87. 20. Binary Search Trees (2/4)
  88. 20. Binary Search Trees (3/4)
  89. 20. Binary Search Trees (4/4)
  90. 21. Parallel Programming Using Threads (1/5)
  91. 21. Parallel Programming Using Threads (2/5)
  92. 21. Parallel Programming Using Threads (3/5)
  93. 21. Parallel Programming Using Threads (4/5)
  94. 21. Parallel Programming Using Threads (5/5)
  95. IV. Applications
  96. 22. Finding the Exit of a Maze (1/5)
  97. 22. Finding the Exit of a Maze (2/5)
  98. 22. Finding the Exit of a Maze (3/5)
  99. 22. Finding the Exit of a Maze (4/5)
  100. 22. Finding the Exit of a Maze (5/5)
  101. 23. Image Processing (1/3)
  102. 23. Image Processing (2/3)
  103. 23. Image Processing (3/3)
  104. 24. Huffman Compression (1/10)
  105. 24. Huffman Compression (2/10)
  106. 24. Huffman Compression (3/10)
  107. 24. Huffman Compression (4/10)
  108. 24. Huffman Compression (5/10)
  109. 24. Huffman Compression (6/10)
  110. 24. Huffman Compression (7/10)
  111. 24. Huffman Compression (8/10)
  112. 24. Huffman Compression (9/10)
  113. 24. Huffman Compression (10/10)
  114. A. Linux
  115. B. Version Control
  116. C. Integrated Development Environments (IDE) (1/3)
  117. C. Integrated Development Environments (IDE) (2/3)
  118. C. Integrated Development Environments (IDE) (3/3)
332 Intermediate C Programming
{
38
int val = array[index];39
printf("delete%d\n", val);40
root = Tree_delete(root, val);41
Tree_print(root);42
}43
}44
Tree_destroy(root);45
free (array);46
return EXIT_SUCCESS;47
}48
20.8 Makefile
The following listing is an example Makefile for compiling and running the code under
valgrind.
CFLAGS = -g -Wall -Wshadow
1
GCC = gcc $(CFLAGS)2
SRCS = treemain.c treesearch.c treedestroy.c treeinsert.c3
SRCS += treeprint.c treedelete.c4
OBJS = $(SRCS:%.c=%.o)5
6
tree: $(OBJS)7
$(GCC) $(OBJS) -o tree8
9
memory: tree10
valgrind --leak-check=yes --verbose ./tree 1011
12
.c.o:13
$(GCC) $(CFLAGS) -c $*.c14
15
clean:16
rm -f *.o a.out tree17
20.9 Counting the Different Shapes of a Binary Tree
How many unique shapes can a binary tree with n nodes possibly have? This is the
definition of shapes. Two binary trees have the same shape if each node has the same
number of left offsprings and the same number of right offsprings. This rule is applied
recursively until reaching leaf nodes. Fig. 20.12 shows the different shapes of trees with two
or three nodes. Table 20.1 gives the number of uniquely shaped binary trees with 1 through
10 nodes.
Binary Search Trees 333
(a)
(b)
FIGURE 20.12: (a) There are two uniquely shaped binary trees with 2 nodes. (b) There
are five uniquely shaped binary trees with 3 nodes.
n 1 2 3 4 5 6 7 8 9 10
number of shapes 1 2 5 14 42 132 429 1430 4862 16796
TABLE 20.1: The numbers of shapes for binary trees of different sizes.
Suppose there are f(n) shapes for a binary tree with n nodes. First note that by obser-
vation we can tell that f (1) = 1 and f (2) = 2 We can use this as a base case for a recursive
function.
If there are k nodes on the left side of the root node, then there must be n k 1 nodes
on the right side or the root node. Here k can be 0, 1, 2, ..., n 1. By definition, the left
subtree has f (k) possible shapes and the right side has f(n k 1) possible shapes. The
shapes on the two sides are independent of each other. This means that for every possible
shape in the left subtree, we count every shape in the right subtree. Thus, if the left subtree
has k nodes, then the total possible number of shapes is: f(k) × f(n k 1). The value of
k is between 0 and n 1 nodes. The total number of shapes is the sum of all the different
possible values of k.
f(n) =
n1
X
k=0
f(k) × f (n k 1) (20.1)
Using recursion is easier because we can assume that simpler (smaller) cases have al-
ready been solved. This formula gives the Catalan numbers in Section 15.4. To prove the
equivalence, let us consider the six possible permutations of 1, 2, 3:
1. < 1, 2, 3 >
2. < 1, 3, 2 >
3. < 2, 1, 3 >
4. < 2, 3, 1 >
5. < 3, 1, 2 >
6. < 3, 2, 1 >
Among these six permutations, < 2, 3, 1 > is not stack sortable as shown in Section 15.4.
Thus, five permutations are stack sortable. Next, consider binary search trees that store the
three numbers.
It is not possible to have < 2, 3, 1 > as the result of pre-order traversal of a binary
search tree that stores 1, 2, and 3. This is not a coincidence. Suppose s(n) is the number
of possible stack-sortable permutations of 1, 2, 3, ..., n. It turns out s(n) is the Catalan
334 Intermediate C Programming
(a) (b) (c) (d) (e)
FIGURE 20.13: Five different shapes for the pre-order traversals of binary search trees
storing 1, 2, and 3. (a) < 1, 2, 3 >, (b) < 1, 3, 2 >, (c) < 2, 1, 3 >, (d) < 3, 2, 1 >, (e)
< 3, 1, 2 >.
numbers as well. As illustrated by the example above, s(n) n! because there are n! possible
permutations of 1, 2,..., n. If n > 2, s(n) must be smaller than n!. We have already seen
that s(3) = 5 3! = 6
Below is a proof that s(n) defines the sequence of Catalan numbers. Suppose a se-
quence of numbers < a
1
, a
2
, a
3
, ...a
n
> is a particular permutation of 1, 2, ..., n and the
sequence is stack-sortable. Any prefix < a
1
, a
2
, a
3
, ...a
k
>, k < n must be stack-sortable.
Suppose a
i
(1 i n) is n (the largest number in the entire sequence). Then the sequence
< a
1
, a
2
, a
3
, ...a
n
> can be divided into three parts:
< a
1
, a
2
, ..., a
i1
> a
i
= n < a
i+1
, a
i+2
, ..., a
n
>
What is the condition that makes a sequence stack-sortable? Section 15.4 explained
that max(a
1
, a
2
, ..., a
i1
) must be smaller than min(a
i+1
, a
i+2
, ..., a
n
). Therefore, the first
sequence must be a permutation of 1, 2, ..., i 1 and the second sequence must be a
permutation of i, i + 1, ..., n 1. Moreover, the two sequences < a
1
, a
2
, ..., a
i1
> and
< a
i+1
, a
i+2
, ..., a
n
> must also be stack-sortable; otherwise, the entire sequence cannot be
stack-sortable. Therefore the entire sequence includes two stack-sortable sequences divided
by a
i
= n. By definition, there are s(i 1) stack-sortable permutations of 1, 2, 3, ..., i 1.
There are s(n i) stack-sortable permutations of i, ..., n 1. The permutations in these two
sequences are independent so there are s(i 1) × s(n i) possible permutations of the two
sequences. The value of i is between 1 and n. When i is 1, the first value in the sequence is
n and this corresponds to the tree in which the root has no left child. When i is n, the last
value is n and this corresponds to the tree in which the root has no right child. Thus, the
total number of stack-sortable permutations is:
s(n) =
n
X
i=1
s(i 1) × s(n i) =
n1
X
i=0
s(i) × s(n i 1). (20.2)
This is the Catalan number.