structured programming instructor: prof. k. t. tsang lecture 11: binary tree 1
TRANSCRIPT
Structured Programming Instructor: Prof. K. T. Tsang
Lecture 11: Binary Tree
1
Binary tree• A structure similar to a
linked-list
• Each node links up to 2 nodes below it
struct bnode {
char data[20];
bnode *left;
bnode *right;
};
data
left right
data
left right
data
left right
node1
node2 node3
2
The tree structure• A node on the
binary tree may have no more than 2 nodes descend from it
• The node on top is called the “root node”
• The bottom nodes are “leaf nodes”
• A node on the binary tree may have no more than 2 nodes descend from it
• The node on top is called the “root node”
• The bottom nodes are “leaf nodes”
0
0 0 0
00
0 0 0 0 0 0 0 0
Root node
Leaf nodes3
Example - parents
struct bnode me, dad, mom;strcpy (me.data, “John”);strcpy (mom.data, “Mary”);strcpy (dad.data, “Lew”);me.left = &dad;me.right = &mom;mom.left = 0;mom.right = 0;dad.left = 0;dad.right =0;
“John”
left right
“Mary”
left right
“Lew”
left right
me
dad mom
0 00 0
4
Example - grandparents
struct bnode grandmom, grandpa, gdmom, gdpa;strcpy (grandmom.data, “Jane”);strcpy (grandpa.data, “Bill”);mom.left = &grandpa;mom.right = &grandmom;grandmom.left = 0;grandmom.right = 0;grandpa.left = 0;grandpa.right =0;
5
Recursive tree-printing
void print_tree (struct bnode *top) {
if (top == NULL) return; //nothing
print_tree (top->left) //print leftprintf ( “%s\n”, top->data); //print this
node
print_tree (top->right); //print right
}
6
Generate random number• int rand ( void );• Returns a pseudo-random integral number in the
range 0 to RAND_MAX, a constant defined in stdlib.h
• This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using srand.
7
8
A typical way to generate pseudo-random numbers in a determined range using rand is to use the modulo of the returned value by the range span and add the initial value of the range:( value % 100 ) is in the range 0 to 99( value % 100 + 1 ) is in the range 1 to 100( value % 30 + 1985 ) is in the range 1985 to 2014
int num= (100*rand())/RAND_MAX;
In the following example, the random seed is initialized to a value representing the second in which the program is executed (time is defined in the header time.h). This way to initialize the seed is generally a good enough option for most random needs.
9
/* rand example: guess the number */#include <stdio.h>#include <stdlib.h>#include <time.h>int main (){ int iSecret, iGuess; /* initialize random seed: */ srand ( time(0) ); /* generate secret number: */ iSecret = rand() % 10 + 1;
do { printf ("Guess the number (1 to 10): "); scanf ("%d",&iGuess); if (iSecret<iGuess) puts ("The secret number is lower"); else if (iSecret>iGuess) puts ("The secret number is higher"); } while (iSecret!=iGuess);
puts ("Congratulations!"); return 0;}
Structured Programming Instructor: Prof. K. T. Tsang
Lecture 12: Miscellaneous:C Preprocessorand Debugging
10
The C Preprocessor• Part of the C compilation process that
analyzes some statements before analysis of the C program itself.
• Preprocessor statements begin with a “pound” sign, ‘#’.
• Some of these statements we have already learned:
#include <stdio.h>#define PI 3.14159#define YES 1#define NO 0
11
“#define” statement#define PI 3.141592654#define YES 1#define TWO_PI 2.0*PI
A defined name is not a variable. You cannot assign a value to it. You use it like a constant.
double area (double r) {return PI * r * r;
}double circum (double r) {
return TWO_PI * r ;} 12
More complicated “#define” - Macros
#define LEAP_YEAR(y) y%4 == 0 && y%100 != 0 || y%400 == 0
#define SQUARE(x) x * x
if (LEAP_YEAR(year)) { … … }//replace by: if (year%4 == 0 && year%100 != 0 || year%400 == 0) if (LEAP_YEAR(next_year)) { … … }
Y = SQUARE ( n1 ) ; //replace by: n1 * n1Y = SQUARE ( u+1) ; //replace by: (u+1)*(u+1)
13
“include” statement
#include <stdio.h> //system include
#include “metric.h” //file provide by you
main () {
float x;
printf (“enter distance in miles\n”);
scanf(“%f”, &x)
printf (“%f miles = %f km\n”, x, MILE_KM * x);
}
14
“metric.h”
#define INCH_PER_CM 0.394
#define CM_PER_INCH 1.0/ INCH_PER_CM
#define MILE_KM 5280.0*12.0* CM_PER_INCH / 100000.0
15
Debugging with “#define”#include <stdio.h>#define DEBUG //same as “#define DEBUG 1”main() {
int i, j, k, nread;nread = scanf (“%d %d %d”, &I, &j, &k);
#ifdef DEBUGprintf (“number of integers read=%i\n”, nread);printf (“i=%i j=%i k=%i\n”, i, j, k);
#endif……
}//scanf returns the number of values successfully read and
assigned. 16
Define preprocessor “name” in the compiler command line
Most compiler allows you to define a name to the preprocessor when the program is compiled by using a special option to the compiler command:
gcc –D DEBUG myProgram.cpp
17
Example: use “ifdef” to debug
Use pointer to write a function with the prototype:char* strConcat(char* s1, char* s2);
to concatenate(连接 ) 2 strings s1 & s2 together and return a pointer points to the resulting string. Use this function in a program to show that it works.
18
#include <stdio.h>#define DEBUG
char* strConcat(char *s1, char *s2){int i = 0, c=0;char *s, s3[99];while (*s1 != '\0') { //check the content is non-null *(s3+i) = *s1;#ifdef DEBUGprintf ("%c", *(s3+i));#endif s1++; i++; //pointer arithmetic to scan the array s1} //end first while loop
19
while (*s2 != '\0') { //check the content is non-null *(s3+i) = *s2;#ifdef DEBUGprintf ("%c", *(s3+i));#endif s2++; i++; //pointer arithmetic to scan the array s2} //end second while loops3[i] = '\0';s = s3; //set pointer to beginning of character array
#ifdef DEBUGprintf ("\n%s\ntotal number of characters : %d\n", s, i);#endif
return s;}
20
int main(){
char str1[99], str2[99], *s0, *s1, *s2; //declare pointers
printf ("Enter 2 strings:");scanf ("%s %s", str1, str2);
//points to the beginning of an character arrays1 = str1;s2 = str2;
//pointers in the arguments and returns0 = strConcat (s1, s2);printf ("After strConcat :%s\n", s0);
return 0;}
21
Summary
• Preprocessor statements begin with a “pound” sign, ‘#’.
• #define statement
• Macros – more complicated use of #define
• #include statement
• Conditional compilation with #ifdef…#endif
• Debugging with #ifdef
22
23
More on Algorithm:1. Write a C function that takes two positive integers as input, then compute and return their Greatest Common Divisor (GCD). This problem can be solved by Euclidean algorithm, an efficient method for computing the GCD and based on the fact that the greatest common divisor of two numbers does not change if the smaller number is subtracted from the larger number. For example, 4 is the GCD of 28 and 12; since 28 − 12 = 16, the GCD of 12 and 16 is also 4. Since the larger of the two numbers is reduced, repeating this process gives successively smaller numbers until one of them is zero.
24
2. Euler's totient function φ(n) of a positive integer n is defined as the number of positive integers less than n that are coprime (or relatively prime, i.e. having no common factor other than 1) to n. In particular φ(1) = 1 since 1 is coprime to itself (1 is the only natural number with this property, and 1 is counted as being relatively prime to all natural numbers). For example, φ(9) = 6 since the six numbers 1, 2, 4, 5, 7 and 8 are coprime to 9. There are eight coprimes of 24 that are less than 24 (1, 5, 7, 11, 13, 17, 19, 23), so φ(24)=8. For a prime number p, φ(p)=p-1, since all numbers less than p are relatively prime to p. Use the gcd function developed in the previous problem to implement a function phi(n) to compute and return the Euler's totient function φ(n) of an input positive integer n.
25
3. Write a C-program to find the relative frequency distribution of the English alphabets by reading a long input text file that contains an English article and count the number of occurrence of each alphabet (disregard whether it is lower or upper cases), then divide it by the total number of the alphabets. Your program should be able to read an input English text file and perform the statistical analysis. Print the result out to a file and the standard output. Check your answer by comparing it with the histogram shown below.
26
#include <stdio.h>void main(){
FILE *f1, *f2; char c; int i, fq[26], n1=0, nt=0; float freq[26];//initialize fq to 0
f1 = fopen (“input.txt”, “r”);f2 = fopen (“output.txt”, “w”);if (f1 == NULL) {printf (“input.txt cannot be opened”); exit(1); }if (f2 == NULL) {printf (“output.txt cannot be opened”); exit(1);}printf (“input.txt & output.txt opened successfully”);
while ((c=getc(f1)) != EOF) {putc(c, f2); printf( “%c”, c); nt++;
if(c==‘a’ || c==‘A’) fq[0]++; //…}
printf (“\n\nTotal characters read: %d\n\n”, nt); fprintf(f2, “\n\nTotal characters read: %d\n\n”, nt); for (i=0; i<26; i++) n1=n1+fq[i]; for (i=0; i<26; i++) freq[i]=float(fq[i])/float(n1); for (i=0; i<26; i++) fprintf(f2, “relative freq: %f\n”, freq[i]);
fclose (f1); fclose (f2);}
27
Caesar Cipher - mono-alphabetic cipher
• replace each letter of message by a letter a fixed distance away (e.g. use the 3rd letter on)
• reputedly used by Julius Caesar
• e.g.
L FDPH L VDZ L FRQTXHUHG
I CAME I SAW I CONQUERED
28
29
The mapping is ABCDEFGHIJKLMNOPQRSTUVWXYZDEFGHIJKLMNOPQRSTUVWXYZABC
30
4. Write a program that can encrypt and decrypt using the general Caesar cipher, also known as an additive cipher.
5. In cryptography, the Cæsar Cipher can be broken by statistical frequency analysis. By knowing the expected distribution of the letters in the original language of the plaintext, we can easily spot the value of the shift by looking at the displacement of particular features of the graph. This is known as frequency analysis. For example in the English language the plaintext frequencies of the letters E, T, (usually most frequent), and Q, Z (typically least frequent) are particularly distinctive. The histogram shown previously exhibits the expected relative frequency distribution of the English alphabets.
31
The simplest numerical integration of a one-dimensional function, f(x), in the range, [a, b], samples function values at regular intervals, f(xn = a + (n - 1/2) Δx) (n = 1, ..., M; Δx = (b − a)/M)
The Monte Carlo method instead generates a sequence of random numbers, rn, in the range, [a, b], and approximates the integral as (the only difference being random instead of regular points)
32
33
Random-number generator in the standard library: The Unix standard library includes a random-number generator, int rand(). Note the header file, #include <stdlib.h>. Successive calls to this routine generate a sequence of random numbers in the range, [0, 231 − 1 = 2,147,483,647].
34
35
36
RAND_MAX is the maximum random number, 2 31 − 1 = 2,147,483,647, defined in /usr/include/stdlib.h. The expression, rand()/(float)RAND_MAX, generates a random number in the range, [0,1].
void srand( (unsigned) time((int *)0) );To initialize the sequence of random numbers, use void srand(unsigned seed), where seed is a random starting point of a sequence. In the above, the seed depends on the time the program is run. The int time(int *tloc) system call returns the time since 00:00:00 GMT, January 1, 1970, measured in seconds. If tloc is nonzero, the return value is also stored in the place to which tloc points.