Advertisement
Guest User

Untitled

a guest
Aug 31st, 2015
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.25 KB | None | 0 0
  1. /* Binary tree "interpreter"
  2. *
  3. * Skeleton program written by Alistair Moffat, September 2014
  4. *
  5. * Modifications by William Pan , October 2014
  6. * Assignment 2 COMP10002
  7. * William Pan 694945
  8. * wpan1
  9. * 694945
  10. *
  11. * Algorithms are fun!
  12. */
  13.  
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <strings.h>
  19. #include <ctype.h>
  20. #include <assert.h>
  21.  
  22. #define LINELEN 80 /* maximum length of any input line */
  23.  
  24. #define RIGHT 1 /* right traversal of tree */
  25. #define LEFT 0 /* left traversal of tree */
  26.  
  27. #define INSERT 'i' /* command to add a string */
  28. #define PRINT1 'p' /* command to do plain print */
  29. #define PRINT2 's' /* command to do snazzy print */
  30. #define ROTATE 'r' /* command to do a tree edge rotation */
  31. #define TABULA 't' /* command to tabulate statistics */
  32. #define FREEIT 'f' /* command to free all space */
  33. #define ALLOPS "irpstf" /* list of all valid operators */
  34. #define FILINP 1 /* indicates input coming from a file */
  35. #define PROMPT "> "
  36.  
  37.  
  38. /****************************************************************/
  39.  
  40. typedef struct node tree_t;
  41.  
  42. struct node {
  43. char *str;
  44. tree_t *left, *rght;
  45. };
  46.  
  47. /****************************************************************/
  48.  
  49. /* Function prototypes */
  50.  
  51. int checkargs(int argc, char **argv);
  52. void print_prompt();
  53. int read_line(int fileinput, char *line, int maxlen);
  54. tree_t *process_line(tree_t *root, char *line);
  55. tree_t *do_insert(tree_t *root, char *str);
  56. tree_t *do_rotate(tree_t *root, char *str);
  57. tree_t *go_to(tree_t *root, char *str);
  58. tree_t *go_to_prev(tree_t *root,tree_t *prev, char *str);
  59. void do_print_p(tree_t *root);
  60. void do_print_p_2(tree_t *root, int level);
  61. void do_print_s(tree_t *root);
  62. void do_print_s_2(tree_t *root, int level, int *history, int lr);
  63. int do_print_s_3(int *history,int p_space, int level);
  64. void do_tabulate(tree_t *root);
  65. int do_t_size(tree_t *root);
  66. int do_t_alldepth(tree_t *root,int level);
  67. int do_t_maxdepth(tree_t *root,int level);
  68. void do_freeit(tree_t *root);
  69.  
  70. /****************************************************************/
  71.  
  72. /* Main program controls all the action */
  73. int
  74. main(int argc, char *argv[]) {
  75. char line[LINELEN+1];
  76. int fileinput=0;
  77. tree_t *root=NULL;
  78. /* check commandline, process argv */
  79. fileinput = checkargs(argc, argv);
  80. /* start the main execution loop */
  81. print_prompt();
  82. while (read_line(fileinput, line, LINELEN)) {
  83. if (strlen(line)>0) {
  84. /* non empty line, so process it */
  85. root = process_line(root, line);
  86. }
  87. /* then round we go */
  88. print_prompt();
  89. }
  90. /* all done, so pack up and go home */
  91. printf("Ta daaa!\n");
  92. return 0;
  93. }
  94.  
  95. /****************************************************************/
  96.  
  97. /* If there is a valid filename on the commandline, redirect stdin
  98. * so that the file is read, and return FILINP to show that input
  99. * input lines should be echoed to the output when they are read */
  100. int
  101. checkargs(int argc, char **argv) {
  102. if (argc==2) {
  103. if (freopen(argv[1], "r", stdin)==NULL) {
  104. printf("Unable to open \"%s\"\n", argv[1]);
  105. exit(EXIT_FAILURE);
  106. }
  107. /* stdin successfully reopened to the named file */
  108. printf("Input file: %s\n", argv[1]);
  109. return FILINP;
  110. } else if (argc>2) {
  111. printf("Usage: %s [filename]\n", argv[0]);
  112. exit(EXIT_FAILURE);
  113. }
  114. /* no command line parameters, so stdin is used unchanged */
  115. return 0;
  116. }
  117.  
  118. /****************************************************************/
  119.  
  120. /* Print the "ready for input" prompt */
  121. void
  122. print_prompt() {
  123. printf(PROMPT);
  124. }
  125.  
  126. /****************************************************************/
  127.  
  128. /* Read a line of input into the array passed as argument
  129. * Returns false if there is no input available
  130. * All whitespace characters are removed */
  131. int
  132. read_line(int fileinput, char *line, int maxlen) {
  133. int i=0, c;
  134. /* get a whole input line, retain non-blanks only */
  135. while (((c=getchar())!=EOF) && (c!='\n')) {
  136. if (i<maxlen && !isspace(c)) {
  137. line[i++] = c;
  138. }
  139. }
  140. line[i] = '\0';
  141. if (fileinput) {
  142. /* print out the input command */
  143. if (line[0]) {
  144. printf("%c", line[0]);
  145. }
  146. if (i>1) {
  147. /* and the argument */
  148. printf(" %s", line+1);
  149. }
  150. printf("\n");
  151. }
  152. return ((i>0) || (c!=EOF));
  153. }
  154.  
  155. /****************************************************************/
  156.  
  157. /* Process a command by parsing the input line into parts, returns
  158. a tree build from the old one by returning a new root pointer */
  159. tree_t
  160. *process_line(tree_t *root, char *line) {
  161. int optype;
  162. /* determine the operation to be performed, it
  163. * must be first character in line
  164. */
  165. optype = line[0];
  166. if (strchr(ALLOPS, optype) == NULL) {
  167. printf("Unknown operator\n");
  168. return root;
  169. }
  170. /* determine the string argument (if one is required),
  171. * it must start in second character of line
  172. */
  173. if (optype==PRINT1 || optype==PRINT2 ||
  174. optype==TABULA || optype==FREEIT) {
  175. if (strlen(line)>1) {
  176. printf("No argument required\n");
  177. return root;
  178. }
  179. }
  180. if (optype==INSERT || optype==ROTATE) {
  181. if (strlen(line)<2) {
  182. printf("An argument is required\n");
  183. return root;
  184. }
  185. }
  186. /* finally, do the actual operation
  187. */
  188. if (optype == PRINT1) {
  189. do_print_p(root);
  190. return root;
  191. } else if (optype == PRINT2) {
  192. do_print_s(root);
  193. return root;
  194. } else if (optype == TABULA) {
  195. do_tabulate(root);
  196. return root;
  197. } else if (optype == FREEIT) {
  198. do_freeit(root);
  199. return NULL;
  200. } else if (optype == INSERT) {
  201. return do_insert(root, line+1);
  202. } else if (optype == ROTATE) {
  203. return do_rotate(root, line+1);
  204. }
  205. /* should never get here, but keeps compiler silent... */
  206. return root;
  207. }
  208.  
  209. /****************************************************************/
  210.  
  211. /* Print out a tree, simple formatting */
  212. void
  213. do_print_p(tree_t *root) {
  214. do_print_p_2(root, 0);
  215. }
  216.  
  217. /****************************************************************/
  218.  
  219. /* Finds each word in reverse-alphabetic order,
  220. printing spaces according to it's level */
  221. void
  222. do_print_p_2(tree_t *root, int level) {
  223. int p_space = 0;
  224. /* Double recursive loop traversing down right
  225. leaves first - reverse alphabetic order */
  226. if (root != NULL){
  227. do_print_p_2(root->rght,level + 1);
  228. /* Print space according to current level */
  229. while(p_space<5*(level)){
  230. printf(" ");
  231. p_space++;
  232. }
  233. printf("%s\n",root->str);
  234. do_print_p_2(root->left,level + 1);
  235. }
  236. }
  237.  
  238. /****************************************************************/
  239.  
  240. /* print out a tree, snazzy formatting */
  241. void
  242. do_print_s(tree_t *root) {
  243. /* Creates history array of max depth of tree */
  244. int maxdepth = do_t_maxdepth(root,0);
  245. int *history = malloc(maxdepth*sizeof(root->str));
  246. /* Snazzy print function part 2 */
  247. do_print_s_2(root, 0, history, -1);
  248. }
  249.  
  250. /****************************************************************/
  251.  
  252. /* Finds each word in reverse-alphabetic order,
  253. printing spaces according to it's level */
  254. void
  255. do_print_s_2(tree_t *root, int level, int *history, int lr) {
  256. int p_space = 0;
  257. /* Adds left or right traversal to history array */
  258. if (lr == RIGHT) history[level] = RIGHT;
  259. else history[level] = LEFT;
  260. /* Double recursive loop traversing down right
  261. leaves first - reverse alphabetic order */
  262. if (root != NULL){
  263. do_print_s_2(root->rght, level + 1, history, RIGHT);
  264. /* Print space according to current level
  265. Five spaces for the rest of the str and prints
  266. '|' if needed */
  267. while(p_space<5*(level)-3){
  268. /* Checks if '|' is needed */
  269. if (do_print_s_3(history,p_space,level)){
  270. printf("|");
  271. p_space++;
  272. }
  273. printf(" ");
  274. p_space++;
  275. }
  276. /* Print string with +-- */
  277. if (level>0) printf("+--%s\n",root->str);
  278. else printf("%s\n",root->str);
  279. do_print_s_2(root->left,level + 1,history, LEFT);
  280. }
  281. else{
  282. /* Print NULL (empty) leaf with +-- */
  283. if (level>0){
  284. while(p_space<5*(level)-3){
  285. if (do_print_s_3(history,p_space,level)){
  286. printf("|");
  287. p_space++;
  288. }
  289. printf(" ");
  290. p_space++;
  291. }
  292. printf("+--\n");
  293. }
  294. }
  295. }
  296.  
  297. /****************************************************************/
  298.  
  299. /* Checks if | needs to be printed */
  300. int
  301. do_print_s_3(int *history,int p_space, int level){
  302. /* If tree traverses in alternating directions (i.e right then left
  303. or right then left) '|' is printed at corresponding level */
  304. if (level>0 && ((p_space+3) % 5*(level) == 0)
  305. && history[(p_space-2)/5+1] != history[(p_space-2)/5+2]){
  306. return 1;
  307. }
  308. return 0;
  309. }
  310.  
  311. /****************************************************************/
  312.  
  313. /* update the tree by adding in the new string; if already there
  314. return the same tree */
  315. tree_t
  316. *do_insert(tree_t *root, char *str) {
  317. /* If the tree is empty, new node is created at root
  318. location */
  319. if (root == NULL) {
  320. root = malloc(sizeof(tree_t));
  321. root->str = malloc(strlen(str)*sizeof(str));
  322. assert(root->str);
  323. strcpy(root->str,str);
  324. root->rght = NULL;
  325. root->left = NULL;
  326. return root;
  327. }
  328. /* Recursive calls to traverse down right side first
  329. until a NULL pointer is found */
  330. else {
  331. if (strcmp(str,root->str) < 0) {
  332. root->left = do_insert(root->left, str);
  333. }
  334. else if (strcmp(str,root->str) > 0) {
  335. root->rght = do_insert(root->rght, str);
  336. }
  337. /* Return the root pointer (unchanged) */
  338. return root;
  339. }
  340. }
  341.  
  342. /****************************************************************/
  343.  
  344. /* Update the tree by rotating it at item specified, return the
  345. new root; if item is not there, return the original tree */
  346. tree_t
  347. *do_rotate(tree_t *root, char *str) {
  348. /* Node of str and node before str defined */
  349. tree_t *root_str = go_to(root, str);
  350. tree_t *root_str_prev = go_to_prev(root, NULL, str);
  351. char *temp = 0;
  352. /* If string not found or already
  353. at top of tree, return original tree */
  354. if (root_str == NULL || root_str_prev == NULL) {
  355. return root;
  356. }
  357. /* Replaces entire root_str_prev leaf and root_str leaf
  358. with respective outcomes when rotated left */
  359. if (root_str_prev->rght != NULL &&
  360. strcmp(root_str_prev->rght->str,root_str->str) == 0){
  361. /* Swapping pointers */
  362. root_str_prev->rght = root_str->rght;
  363. root_str->rght = root_str->left;
  364. root_str->left = root_str_prev->left;
  365. root_str_prev->left = root_str;
  366. /* Swapping strings of main pointers */
  367. temp = root_str_prev->str;
  368. root_str_prev->str = root_str->str;
  369. root_str->str = temp;
  370. }
  371. /* Replaces entire root_str_prev leaf and root_str leaf
  372. with respective outcomes when rotated right */
  373. else if (root_str_prev->left != NULL &&
  374. strcmp(root_str_prev->left->str,root_str->str) == 0){
  375. /* Swapping pointers */
  376. root_str_prev->left = root_str->left;
  377. root_str->left = root_str->rght;
  378. root_str->rght = root_str_prev->rght;
  379. root_str_prev->rght = root_str;
  380. /* Swapping strings of main pointers */
  381. temp = root_str_prev->str;
  382. root_str_prev->str = root_str->str;
  383. root_str->str = temp;
  384. }
  385. /* Return the root pointer (unchanged) */
  386. return root;
  387. }
  388.  
  389. /****************************************************************/
  390.  
  391. /* Return the *node of where previous string is */
  392. tree_t
  393. *go_to_prev(tree_t *root,tree_t *prev, char *str) {
  394. if (root != NULL){
  395. /* If string found return locaton */
  396. if(strcmp(root->str, str) == 0){
  397. return prev;
  398. }
  399. /* If string larger than node->str go to rght pointer */
  400. if(strcmp(root->str,str) < 0){
  401. prev = root;
  402. return go_to_prev(root->rght, root, str);
  403. }
  404. /* If string larger than node->str go to left pointer */
  405. if(strcmp(root->str,str) > 0){
  406. prev = root;
  407. return go_to_prev(root->left, root, str);
  408. }
  409. }
  410. return prev;
  411. }
  412.  
  413. /****************************************************************/
  414.  
  415. /* Return the *node of where string is NULL returned if not found */
  416. tree_t
  417. *go_to(tree_t *root, char *str) {
  418. if (root != NULL){
  419. /* If string found return locaton */
  420. if(strcmp(root->str,str) == 0){
  421. return root;
  422. }
  423. /* If string larger than node->str go to rght pointer */
  424. if(strcmp(root->str,str) < 0){
  425. return go_to(root->rght, str);
  426. }
  427. /* If string larger than node->str go to left pointer */
  428. if(strcmp(root->str,str) > 0){
  429. return go_to(root->left, str);
  430. }
  431. }
  432. return root;
  433. }
  434.  
  435. /****************************************************************/
  436.  
  437. /* Print the final size of the tree, and average node depth */
  438. void
  439. do_tabulate(tree_t *root) {
  440. int size = 0, maxdepth = 0;
  441. double alldepth = 0;
  442. /* Size of tree */
  443. size = do_t_size(root);
  444. printf("size :%6d\n",size);
  445. /* If empty, do not print average or max depth */
  446. if (size){
  447. /* Sum of depth of each element */
  448. alldepth = do_t_alldepth(root,0);
  449. printf("avg depth:%6.2f\n",alldepth/size);
  450. /* Max depth of tree */
  451. maxdepth = do_t_maxdepth(root,0);
  452. printf("max depth:%6d\n",maxdepth);
  453. }
  454.  
  455. }
  456.  
  457. /****************************************************************/
  458.  
  459. /* Find the number of elements in tree */
  460. int
  461. do_t_size(tree_t *root) {
  462. /* Recursive loop adds one for every traversal */
  463. if (root != NULL) {
  464. return(do_t_size(root->rght) + do_t_size(root->left) + 1);
  465. }
  466. else {
  467. return 0;
  468. }
  469. }
  470.  
  471. /****************************************************************/
  472.  
  473. /* Adds all the levels of nodes */
  474. int
  475. do_t_alldepth(tree_t *root,int level) {
  476. int lnum = 0, rnum = 0, total = 0;
  477. /* Recursive loop adds the level of all elements in tree
  478. +1 added to total as root node == 0 */
  479. if (root != NULL) {
  480. lnum = do_t_alldepth(root->rght, level + 1);
  481. rnum = do_t_alldepth(root->left, level + 1);
  482. total += level + lnum + rnum + 1;
  483. }
  484. return total;
  485. }
  486.  
  487. /****************************************************************/
  488.  
  489. /* Find the maximum depth of tree */
  490. int
  491. do_t_maxdepth(tree_t *root,int level) {
  492. int lnum = 0, rnum = 0;
  493. /* Recursive loop adds one at end of tree */
  494. if (root != NULL) {
  495. lnum = do_t_maxdepth(root->rght, level + 1);
  496. rnum = do_t_maxdepth(root->left, level + 1);
  497. }
  498. /* Returns max level, first root node is 0, however NULL
  499. nodes also add to total */
  500. if (lnum > rnum) {
  501. if (lnum > level) return lnum;
  502. }
  503. if (rnum > level) return rnum;
  504. return level;
  505. }
  506.  
  507. /****************************************************************/
  508.  
  509. /* Free all of the space, and make empty tree again */
  510. void
  511. do_freeit(tree_t *root) {
  512. if (root != NULL){
  513. do_freeit(root->rght);
  514. do_freeit(root->left);
  515. free(root);
  516. }
  517. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement