修改程序清单17.2,使其既能以正序又能以逆序显示电影列表。一种方法修改链表定义以使链表能被双向遍历;另一种方法是使用递归。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define TSIZE 45 typedef struct film { char title[TSIZE]; int rating; struct film * next; struct film * up; }Film; void positive(Film * p); //正序显示 void reversed(Film * p); //逆序显示 void recursion(Film * p); //逆序递归显示 void empty(Film * p); int main(void) { Film * head = NULL; //指向链表头结点的指针,始终指向头结点保持不变 Film * current; //动态内存分配的地址。 Film * prev; //尾结点,可变,每次用来更新结构体内指针变量的值和自身的值。 char input[TSIZE]; puts("Enter first movie title: "); while (gets(input) != NULL && input[0] != '\0') { current = (Film *)malloc(sizeof(Film)); /* if ((current = (Film *)malloc(sizeof(Film))) == NULL) { printf("内存分配失败:\n"); exit(EXIT_FAILURE); } */ if (head == NULL) { head = current; current->up = NULL; } else { prev->next = current; current->up = prev; } current->next = NULL; strcpy(current->title, input); puts("Enter your rating <0-10>: "); scanf("%d", ¤t->rating); while (getchar() != '\n') continue; puts("Enter next movie title (empty line to stop): "); prev = current; } if (head == NULL) printf("No data entered. "); else { printf("Here is the movie list: \n"); positive(head); printf("\n"); printf("Here is the movie list: \n"); reversed(prev); printf("\n"); printf("Here is the movie list: \n"); recursion(head); } printf("Bye!\n"); return 0; } void positive(Film * p) { while (p != NULL) { printf("Movie: %s Rating: %d\n", p->title, p->rating); p = p->next; } } void reversed(Film * p) { while (p != NULL) { printf("Movie: %s Rating: %d\n", p->title, p->rating); p = p->up; } } void recursion(Film * p) { if (p->next != NULL) recursion(p->next); printf("Movie: %s Rating: %d\n", p->title, p->rating); } void empty(Film * p) { Film * temp; while (p != NULL) { temp = p; p = p->next;; free(temp); } }
2.假设list.h(程序清单17.3)如下定义列表:
typedef struct list
{
Node * nead; /*指向列表首*/
Node * end; /*指向列表尾*/
}List;
根据这个定义,重写list.c(程序清单17.5)函数,并用films3.c(程序清单17.4)测试结果代码。
/* 重写list.c */ #include <stdio.h> #include <stdlib.h> #include "list_17_3.h" static void CopyToNode(Item item, Node * pnode); void InitializeList(List * plist) { //plist = NULL; //Error plist是一个变量地址,只能改变变量的值 ,不能改变地址。 plist->head = NULL; plist->end = NULL; } bool ListIsEmpty(const List * plist) { if (plist->head == NULL) return true; else return false; } bool ListIsFull(const List * plist) { //判定内存是否有足够空间,可以不传递形参 Node * pt; bool full; pt = (Node *)malloc(sizeof(Node)); if (pt == NULL) full = true; else full = false; free(pt); return full; } unsigned int ListItemCount(const List * plist) { unsigned int count = 0; Node * pnode = plist->head; while (pnode != NULL) { ++count; pnode = pnode->next; } return count; } bool AddItem(Item item, List * plist) { Node * pnew; Node * scan = plist->head; pnew = (Node *)malloc(sizeof(Node)); if (pnew == NULL) return false; CopyToNode(item, pnew); pnew->next = NULL; if (scan == NULL) plist->head = pnew; else plist->end->next = pnew; plist->end = pnew; return true; } void Traverse(const List * plist, void(*pfun)(Item item)) { Node * pnode = plist->head; while (pnode != NULL) { (*pfun)(pnode->item); pnode = pnode->next; } } void EmptyTheList(List * plist) { Node * psave; while (plist->head != NULL) { psave = plist->head->next; free(plist->head); plist->head = psave; } } static void CopyToNode(Item item, Node * pnode) { pnode->item = item; }
3.假设list.h(程序清单17.3)如下定义列表:
#define MAXZIZE 100
typedef struct list
{
Item entries[MAXAIZE]; /*项目数组*/
int items; /*列表中项目的个数*/
}List;
根据这个定义,重写list.c(程序清单17.5)函数,并用films3.c(程序清单17.4)测试结果代码
/* 重写list.c */ #include <stdio.h> #include <stdlib.h> #include "list_17_3.h" static void CopyToNode(Item item, Item * pnode); void InitializeList(List * plist) { plist->items = 0; } bool ListIsEmpty(const List * plist) { if (plist->items == 0) return true; else return false; } bool ListIsFull(const List * plist) { if (plist->items < MAXSIZE) return false; else return true; } unsigned int ListItemCount(const List * plist) { return plist->items; } bool AddItem(Item item, List * plist) { int i = plist->items; if (i < MAXSIZE) { CopyToNode(item, &plist->entries[i]); plist->items++; return true; } return false; } void Traverse(const List * plist, void(*pfun)(Item item)) { int i; for (i = 0; i < plist->items; i++) (*pfun)(plist->entries[i]); } void EmptyTheList(List * plist) { plist->items = 0; } static void CopyToNode(Item item, Node * pnode) { pnode->item = item; }
4.重写mall.c(程序清单17.7)使其用两个队列模拟两个摊位。
//mall.c明明是程序清单17.9,书上搞错了???
/* 重写mall.c 用两个队列模拟二个摊位*/ /* 以分钟为单位程序有局限性。 当有两个摊位时,因为每分钟才会有一个顾客生成,所以一个小时最多只可能有60个顾客 就算每个顾客都要三分钟,那么两个摊位可以接客40人,再加上两个队列可容纳20人 所以永远不可能出现被拒绝加入队列的情况。 */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include "queue.h" #define MIN_PER_HR 60.0 bool newcustomer(double x); Item customertime(long when); int main(void) { Queue line1, line2; Item temp; int hours; int perhour; long cycle, cyclelimit; long turnaways = 0; long customers = 0; long served1 = 0, served2 = 0; long sum_line1 = 0, sum_line2 = 0; int wait_time1 = 0, wait_time2 = 0; double min_per_cust; long line_wait1 = 0, line_wait2 = 0; InitQueue(&line1); InitQueue(&line2); srand((unsigned)time(NULL)); puts("Case Study: Sigmund Lander's Advice Booth"); puts("Enter the number of simulation hours:"); scanf("%d", &hours); //以秒为单位 cyclelimit = MIN_PER_HR * hours; puts("Enter the average number of customers per hour: "); scanf("%d", &perhour); min_per_cust = perhour / MIN_PER_HR; printf("%.2lf\n", min_per_cust); int i = 0; for (cycle = 0; cycle < cyclelimit; cycle++) { if (newcustomer(min_per_cust)) { i++; if (QueueIsFull(&line1) && QueueIsFull(&line2)) turnaways++; else { customers++; temp = customertime(cycle); if (QueueItemCount(&line1) < QueueItemCount(&line2)) EnQueue(temp, &line1); else EnQueue(temp, &line2); } } if (wait_time1 <= 0 && !QueueIsEmpty(&line1)) { DeQueue(&temp, &line1); wait_time1 = temp.processtime; line_wait1 += cycle - temp.arrive; served1++; } if (wait_time2 <= 0 && !QueueIsEmpty(&line2)) { DeQueue(&temp, &line2); wait_time2 = temp.processtime; line_wait2 += cycle - temp.arrive; served2++; } if (wait_time1 > 0) wait_time1--; if (wait_time2 > 0) wait_time2--; sum_line1 += QueueItemCount(&line1); sum_line2 += QueueItemCount(&line1); } if (customers > 0) { //两个摊位总的营业情况 printf("customers accepted: %ld\n", customers); printf(" custmers served: %ld\n", served1 + served2); printf(" turnaways: %ld\n", turnaways); printf("average queue size: %.2f\n", (double)(sum_line1 + sum_line2) / cyclelimit); printf("average wait time: %.2f minutes\n", (double)(line_wait1 + line_wait2) / (served1 + served2)); } else puts("No customers!"); printf("i = %d\n", i); return 0; } bool newcustomer(double x) { if (rand()*x / RAND_MAX < 1) return true; else return false; } Item customertime(long when) { Item cust; cust.processtime = rand() % 3 + 1; cust.arrive = when; return cust; }
5.编写一个程序,让您输入一个字符串。该程序将此字符串中的字符逐个地压入一个栈(请参见复习题5),然后弹出这些字符并显示。结果是将字符串按逆序显示。
/* stack.h -- 栈接口 */ #ifndef _STACK_H_ #define _STACK_H_ #include <stdbool.h> typedef char Item; typedef struct node { Item item; struct node * next; } Node; typedef struct stack{ Node * top; Node * bottom; }Stack; void InitStack(Stack * ps); bool StackIsFull(const Stack * ps); bool StackIsEmpty(const Stack * ps); int StackItemCount(const Stack * ps); bool push(Item item, Stack * ps); bool Pop(Item * pitem, Stack * ps); #endif
/* stack.c -- 栈相关函数定义 */ #include <stdio.h> #include <stdlib.h> #include "stack.h" static void CopyToNode(Item item, Node * pn); static void CopyToItem(Node * pn, Item * pi); void InitStack(Stack * ps) { ps->bottom = ps->top = NULL; } bool StackIsFull(const Stack * ps) { Node * temp; temp = (Node *)malloc(sizeof(Node)); if (temp == NULL) return true; else free(temp); return false; } bool StackIsEmpty(const Stack * ps) { return ps->top == NULL; } bool push(Item item, Stack * ps) { Node * pnew; if (StackIsFull(ps)) return false; pnew = (Node *)malloc(sizeof(Node)); if (pnew == NULL) { fprintf(stderr, "Unable to allocate memory!\n"); exit(1); } CopyToNode(item, pnew); if (StackIsEmpty(ps)) { pnew->next = NULL; ps->bottom = pnew; } else pnew->next = ps->top; ps->top = pnew; return true; } bool Pop(Item * pitem, Stack * ps) { Node * pt; if (StackIsEmpty(ps)) return false; CopyToItem(ps->top, pitem); pt = ps->top; ps->top = ps->top->next; free(pt); if (ps->top == NULL) ps->bottom = NULL; return true; } static void CopyToNode(Item item, Node * pn) { pn->item = item; } static void CopyToItem(Node * pn, Item * pi) { *pi = pn->item; }
/* test.c -- 测试栈,与stack.c一起编译 */ #include <stdio.h> #include "stack.h" #define STRLEN 80 int main(void) { char str[STRLEN]; Stack stack; int i; Item ch; InitStack(&stack); printf("请输入字符串:"); gets(str); for (i = 0; str[i] != '\0' && i < STRLEN; i++) push(str[i], &stack); printf("出栈输出字符串:"); while (Pop(&ch, &stack)) putchar(ch); putchar('\n'); return 0; }
6.写一个接受3个参数的函数。这3个参数为:存有已排序的整数的数组名,数组元素个数和要查找的整数。如果该整数在数组中,函数返回1;否则返回0。函数用折半搜索法实现。
/* 折半查找1-99中有哪些数包含在数组中 */ #include <stdio.h> #include <stdbool.h> int search(int table[], int max, int number); #define M 10 //前提条件:数组要求有序排列 int table[M] = { 1, 3, 5, 6, 9, 13, 19, 21, 34, 45 }; int main(void) { int i ; for (i = 0; i<100; i++) if (search(table, M-1, i)) printf("%d ", i); printf("\n"); return 0; } int search(int table[], int max, int number) { int min = 0, half; int i = 0; while (1) { i++; half = (min + max) / 2; //最小数加最大数除以2等于这两个数的中间数 if (number > table[half]) { min = half + 1; //确定最小数 } else { if (number < table[half]) max = half - 1; //确定最大数 else return true; } if (min + 1 == max) { //如果重合说明中中间已没有数,直接判断临的两个数 if (number == table[min] || number == table[max]) return true; else return false; } } }
7.编写一个程序,能打开、读入一个文本文件并统计文件中每个单词出现的次数。用改进的二叉搜索树存储单词及出现的次数。程序读入文件后,会提供一个有三个选项的菜单。第一个选项为列出所有的单词连同其出现的次数。第二个选项为让您输入一个单词,程序报告该单词在文件中出现的次数。第三个选项为退出。
/* tree.h */ #ifndef _TEST_H_ #define _TEST_H_ #include <stdbool.h> #define WORDLEN 55 typedef struct item { char word[WORDLEN]; int word_size; }Item; typedef struct node { Item item; struct node * left; struct node * right; }Node; typedef struct tree { Node * root; int node_size; }Tree; void InitTree(Tree * pt); bool TreeIsEmpty(Tree * pt); bool TreeIsFull(Tree * pt); int TreeItemCount(const Tree * pt); bool AddItem(const Item * pi, Tree * pt); Node * InItem(const Item * pi, Tree * pt); bool DeItem(const Item * pi, Tree * pt); void traverse(const Tree * pt, void(* pfun)(Item item)); void DeAll(Tree * pt); #endif
/* tree.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "tree.h" typedef struct pair { Node * parent; Node * child; }Pair; /* 局部函数 */ static Node * MakeNode(const Item * pi); static bool ToLeft(const Item * i1, const Item * i2); static bool ToRight(const Item * i1, const Item * i2); static void AddNode(Node * new_node, Node * root); static void InOrder(const Node * root, void(*pfun)(Item item)); static Pair SeekItem(const Item * pi, const Tree * ptree); static void DeNode(Node ** ptr); static void DeAllNodes(Node * ptr); void InitTree(Tree * pt) { pt->node_size = 0; pt->root = NULL; } bool TreeIsEmpty(Tree * pt) { return pt->root == NULL; } bool TreeIsFull(Tree * pt) { Node * ptemp; ptemp = (Node *)malloc(sizeof(Node)); if (ptemp == NULL) return true; else return false; } int TreeItemCount(const Tree * pt) { return pt->node_size; } bool AddItem(const Item * pi, Tree * pt) { Node * new_node; if (TreeIsFull(pt)) { fprintf(stderr, "Tree is full\n"); return false; } new_node = MakeNode(pi); if (new_node == NULL) { fprintf(stderr, "Couldn't create node\n"); return false; } if (SeekItem(pi, pt).child != NULL) { SeekItem(pi, pt).child->item.word_size++; free(new_node); return true; } if (pt->root == NULL) pt->root = new_node; else AddNode(new_node, pt->root); pt->node_size++; return true; } Node * InItem(const Item * pi, Tree * pt) { return SeekItem(pi, pt).child; } bool DeItem(const Item * pi, Tree * pt) { Pair look; look = SeekItem(pi, pt); if (look.child == NULL) return false; if (look.parent == NULL) DeNode(&pt->root); else if (look.parent->left == look.child) DeNode(&look.parent->left); else if (look.parent->right == look.child) DeNode(&look.parent->right); pt->node_size--; return true; } void traverse(const Tree * pt, void(*pfun)(Item item)) { if (pt != NULL) InOrder(pt->root, pfun); } void DeAll(Tree * pt) { if (pt != NULL) DeAllNodes(pt->root); pt->node_size = 0; pt->root = NULL; } static Node * MakeNode(const Item * pi) { Node * new_node; new_node = (Node *)malloc(sizeof(Node)); if (new_node != NULL) { new_node->item = *pi; new_node->left = NULL; new_node->right = NULL; } return new_node; } static bool ToLeft(const Item * i1, const Item * i2) { if (strcmp(&i1->word[0], &i2->word[0]) < 0) return true; else return false; } static bool ToRight(const Item * i1, const Item * i2) { if (strcmp(&i1->word[0], &i2->word[0]) > 0) return true; else return false; } static void AddNode(Node * new_node, Node * root) { if (ToLeft(&new_node->item, &root->item)) { if (root->left == NULL) root->left = new_node; else AddNode(new_node, root->left); } else { if (ToRight(&new_node->item, &root->item)) { if (root->right == NULL) root->right = new_node; else AddNode(new_node, root->right); } } } static void InOrder(const Node * root, void(*pfun)(Item item)) { if (root != NULL) { InOrder(root->left, pfun); (*pfun)(root->item); InOrder(root->right, pfun); } } static Pair SeekItem(const Item * pi, const Tree * ptree) { Pair look; look.parent = NULL; look.child = ptree->root; if (look.child == NULL) return look; while (look.child != NULL) { if (ToLeft(pi, &look.child->item)) { look.parent = look.child; look.child = look.child->left; } else { if (ToRight(pi, &look.child->item)) { look.parent = look.child; look.child = look.child->right; } else break; } } return look; } static void DeNode(Node ** ptr) { //形参ptr是父节点中用来保存子节点地址的变量,实参让其初始化为父节点的指针域 //*ptr是子节点本身,也就是要删除的节点。 //子节点删除后,将*ptr指向新的节点也就更改了父节点的指针域。 //ptr的值只要不更改,*ptr永远是父节点的指向。 Node * temp; puts((*ptr)->item.word); if ((*ptr)->left = NULL) { temp = *ptr; *ptr = (*ptr)->right; free(temp); } else { if ((*ptr)->right == NULL) { temp = *ptr; *ptr = (*ptr)->left; free(temp); } else { temp = (*ptr)->left; while (temp->right != NULL) temp = temp->right; temp->right = (*ptr)->right; temp = *ptr; *ptr = (*ptr)->left; free(temp); } } } static void DeAllNodes(Node * root) { Node * temp; if (root != NULL) { /* 保存右子树指针 找到左子树为空的节点,释放节点内存 用保存的右子指针找左子树为空的节点,释放内存 直到右子树指针为空 */ temp = root->right; DeAllNodes(root->left); free(root); DeAllNodes(temp); } }
/* test.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "tree.h" void menu(void); int get_ch(char * str); void printItem(Item item); int main(void) { FILE * fp; Tree tree; Item word = { {'\0'}, 1 }; char ch; bool n = false; InitTree(&tree); if ((fp = fopen("f:\\test\\emma.txt", "r")) == NULL) { fprintf(stderr, "文件打开失败\n"); exit(EXIT_FAILURE); } while ((ch=getc(fp)) != EOF) { int i = 0; while (isalpha(ch)) { word.word[i++] = ch; ch = getc(fp); } if (i > 0) { word.word[i++] = '\0'; AddItem(&word, &tree); } //putchar('a'); } putchar('\n'); fclose(fp); menu(); while ((ch = get_ch("abq")) != 'q') { if (ch == 'a') { puts("包含的单词\t\t单词出现的次数"); traverse(&tree, printItem); } if (ch == 'b') { puts("请输入要查找的单词:"); scanf("%s", word.word); while (getchar() != '\n') ; if (InItem(&word, &tree)) { printf("单词%s在文件中出现%d次\n", word.word, InItem(&word, &tree)->item.word_size); } else printf("文件中没有找到单词%s\n", word.word); } printf("\n"); menu(); } } void menu(void) { puts("请输入选项:"); puts("a)列出所有的单词连同其出现的次数"); puts("b)输入一个单词,程序报告该单词在文件中出现的次数"); puts("q)退出程序"); } int get_ch(char * str) { int ch; ch = getchar(); while (getchar() != '\n') ; while (strchr(str, ch) == NULL) { printf("请输入正确的选项%s:", str); ch = getchar(); while (getchar() != '\n') ; } return ch; } void printItem(Item item) { printf("%10s\t\t%14d\n", item.word, item.word_size); }
8.修改宠物俱乐部程序,使所有同名的宠物存储在相同节点中的一个列表中。当用户选择查找一个宠物时,程序要求用户给出宠物名,而后列出所有具有此名字的宠物(连同它们的种类)。
// tree.h -- 二叉搜索树接口 #ifndef _TREE_H #define _TREE_H #include <stdbool.h> #define TREEMAX 20 typedef struct item { char petname[20]; char petkind[20]; }Item; typedef struct node_list { Item item; struct node_list * next; }List; typedef struct node_tree { List * list; //同名宠物的项目列表 int list_size; //列表中项目个数 struct node_tree * left; //指向左分支的指针 struct node_tree * right; //指向右分支的指针 }Node; typedef struct tree { Node * root; //指向树根的指针 int size; //树中项目的个数 }Tree; void InitTree(Tree * ptree); bool TreeIsEmpty(const Tree * ptree); bool TreeIsFull(const Tree * ptree); int TreeItemCount(const Tree * ptree); bool InTree(const Item * pi, const Tree * ptree); bool AddTreeItem(const Item * pi, Tree * ptree); bool DeleteItem(const Item * pi, Tree * ptree); void Traverse(const Tree * ptree, void(*pfun)(List * list)); void DeleteAll(Tree * ptree); #endif
//tree.c -- 接口函数定义 #include <stdio.h> #include <stdlib.h> #include <string.h> #include "tree.h" typedef struct pair { Node * parent; Node * child; }Pair; //局部函数声明 static bool AddListItem(const Item * pi, Node * root); static List * MakeListNode(const Item * pi); static Node * MakeTreeNode(const Item * pi); static void AddTreeNode(Node * new_node, Node * root); static Pair SeekItem(const Item * pi, const Tree * ptree); static bool ToLeft(const Item * i1, const Item * i2); static bool ToRight(const Item * i1, const Item * i2); static bool SeekListItem(const Item * pi, List * pl); static void DeNode(const Item * pi, Node ** ptr); static List * DeListNode(const Item * pi, List * pl); static void InOrder(const Node * root, void(*pfun)(List * list)); static void DeleteAllNodes(Node * root); static void DeList(List * list); static void DeleteAllList(Node * root); //局部函数定义 static bool AddListItem(const Item * pi, Node * root) { //OK List * new_listnode, *temp = root->list; new_listnode = MakeListNode(pi); if (new_listnode == NULL) { fprintf(stderr, "新的成员生成失败\n"); return false; } while (NULL != temp->next) temp = temp->next; temp->next = new_listnode; root->list_size++; return true; } static List * MakeListNode(const Item* pi) { //OK List * new_list; new_list = (List *)malloc(sizeof(List)); if (new_list != NULL) { new_list->item = *pi; new_list->next = NULL; } return new_list; } static Node * MakeTreeNode(const Item * pi) { //OK Node * new_node; List * new_list_node; new_list_node = MakeListNode(pi); if (new_list_node == NULL) return NULL; new_node = (Node *)malloc(sizeof(Node)); if (new_node != NULL) { new_node->list = new_list_node; new_node->list_size = 1; new_node->left = NULL; new_node->right = NULL; } return new_node; } static void AddTreeNode(Node * new_node, Node * root) { //OK if (ToLeft(&new_node->list->item, &root->list->item)) { if (NULL == root->left) root->left = new_node; } else if (ToRight(&new_node->list->item, &root->list->item)) { if (NULL == root->right) root->right = new_node; } } static bool ToLeft(const Item * i1, const Item * i2) { //OK if (strcmp(i1->petname, i2->petname) < 0) return true; return false; } static bool ToRight(const Item * i1, const Item * i2) { //OK if (strcmp(i1->petname, i2->petname) > 0) return true; return false; } static bool SeekListItem(const Item * pi, List * pl) { //OK List * temp = pl; while (NULL != temp) { if (strcmp(pi->petkind, temp->item.petkind) == 0) return true; temp = temp->next; } return false; } static Pair SeekItem(const Item * pi, const Tree * ptree) { //OK Pair look; look.parent = NULL; look.child = ptree->root; if (NULL == look.child) return look; while (NULL != look.child) { if (ToLeft(pi, &look.child->list->item)) { look.parent = look.child; look.child = look.child->left; } else if (ToRight(pi, &look.child->list->item)) { look.parent = look.child; look.child = look.child->right; } else { break; } } return look; } static void DeNode(const Item * pi, Node ** ptr) { //OK Node * temp; if (1 == (*ptr)->list_size) { //列表内只有一个项目,删整个节点 if (NULL == (*ptr)->left) { temp = *ptr; *ptr = (*ptr)->right; free(temp); } else if (NULL == (*ptr)->right) { temp = *ptr; *ptr = (*ptr)->left; free(temp); } else { temp = (*ptr)->left; while (NULL != temp->right) temp = temp->right; temp->right = (*ptr)->right; temp = *ptr; *ptr = (*ptr)->left; free(temp); } } else if ((*ptr)->list_size > 1) { //列表内有多个项目,删列表中的一个项目 (*ptr)->list = DeListNode(pi, (*ptr)->list); (*ptr)->list_size--; } } static List * DeListNode(const Item * pi, List * pl) { //OK List * phead = pl; //保存链表头指针 List * temp; if (strcmp(pi->petkind, phead->item.petkind) == 0) { phead = pl->next; free(pl); } else { do { temp = pl; pl = pl->next; } while (strcmp(pi->petkind, pl->item.petkind) != 0); temp->next = pl->next; free(pl); } return phead; } static void InOrder(const Node * root, void(*pfun)(List * list)) { //OK if (root != NULL) { InOrder(root->left, pfun); (*pfun)(root->list); InOrder(root->right, pfun); } } static void DeleteAllNodes(Node * root) { Node * temp = root; if (root != NULL) { temp = root->right; DeleteAllNodes(root->left); DeList(root->list); free(root); DeleteAllNodes(temp); } } static void DeList(List * list) { List * temp; while (list != NULL) { temp = list; list = list->next; free(temp); } } //全局函数定义 void InitTree(Tree * ptree) { //OK ptree->root = NULL; ptree->size = 0; } bool TreeIsEmpty(const Tree * ptree) { //OK return ptree->root == NULL; } bool TreeIsFull(const Tree * ptree) { //OK return ptree->size >= TREEMAX; } int TreeItemCount(const Tree * ptree) { //OK return ptree->size; } bool InTree(const Item * pi, const Tree * ptree) { Pair look = SeekItem(pi, ptree); return look.child != NULL && SeekListItem(pi, look.child->list); } bool AddTreeItem(const Item * pi, Tree * ptree) { //OK Node * new_node; Pair seek; if (TreeIsFull(ptree)) { fprintf(stderr, "Tree is ull\n"); return false; } seek = SeekItem(pi, ptree); if (seek.child != NULL) { if (AddListItem(pi, seek.child)); return true; return false; } new_node = MakeTreeNode(pi); if (new_node == NULL) { fprintf(stderr, "Couldn't create node\n"); return false; } if (ptree->root == NULL) ptree->root = new_node; else AddTreeNode(new_node, ptree->root); ptree->size++; return true; } bool DeleteItem(const Item * pi, Tree * ptree) { //OK Pair look; look = SeekItem(pi, ptree); int i = TreeItemCount(ptree); if (NULL == look.child) return false; //是否找到同名项 if (!SeekListItem(pi, look.child->list)) return false; //是否找到同类项 DeNode(pi, &look.child); int j = TreeItemCount(ptree); if (i == j) ptree->size--; if (ptree->size == 0) ptree->root = NULL; return true; } void Traverse(const Tree * ptree, void(*pfun)(List * list)) { //OK if (ptree->root != NULL) InOrder(ptree->root, pfun); } void DeleteAll(Tree * ptree) { if (ptree->root != NULL) DeleteAllNodes(ptree->root); ptree->size = 0; }
//test_tree.c -- 测试二叉搜索树 #include <stdio.h> #include <string.h> #include <ctype.h> #include "tree.h" char menu(void); //显示菜单,判定用用户输入 void addpet(Tree * pt); //添加内容 void droppet(Tree * pt); //删除项目 void showpets(const Tree * pt); //显示整个树 void findpet(const Tree * pt); //搜索某个项目是否在树中 void printitem(List * list); //打印项目内容 void uppercase(char * str); //转换大写 int ListItemCount(Node * root); int main(void) { Tree pets; //定义树变量 char choice; int conut=0, temp=0; InitTree(&pets); while ((choice = menu()) != 'q') { switch (choice) { case 'a': addpet(&pets); break; case 'l': showpets(&pets); break; case 'f': findpet(&pets); break; case 'n': conut = ListItemCount(pets.root); conut -= temp; temp += conut; printf("%d pets in club\n", conut); break; case 'd': droppet(&pets); break; default: puts("Switching error"); } } DeleteAll(&pets); puts("Bye."); return 0; } char menu(void) { int ch; puts("Nerfville pet Club Membership Program"); puts("Enter the letter corresponding to your choice: "); puts("a)add a per l)show list of pets"); puts("n)number of pets f)find pets"); puts("d)delete apet q)quit"); while ((ch = getchar()) != EOF) { while (getchar() != '\n') //丢弃输入行的剩余部分 continue; ch = tolower(ch); if (strchr("alrfndq", ch) == NULL) puts("Please enter an a, l, f, n, d, or q: "); else break; } if (ch == EOF) //令EOF导致程序退出 ch = 'q'; return ch; } void addpet(Tree * pt) { Item temp; if (TreeIsFull(pt)) //树已满 puts("No room in the club!"); //提示无空间 else { // puts("Please enter name of pet: "); gets(temp.petname); puts("Please enter pet kind: "); gets(temp.petkind); uppercase(temp.petname); uppercase(temp.petkind); AddTreeItem(&temp, pt); } } void showpets(const Tree * pt) { if (TreeIsEmpty(pt)) puts("No enteries!"); else Traverse(pt, printitem); } void printitem(List * list) { while (list != NULL) { printf("pet: %-19s kind: %-19s\n", list->item.petname, list->item.petkind); list = list->next; } } void findpet(const Tree * pt) { Item temp; if (TreeIsEmpty(pt)) { puts("No entries!"); return; } puts("Please enter name of pet you wish to find: "); gets(temp.petname); puts("Please enter pet kind: "); gets(temp.petkind); uppercase(temp.petname); uppercase(temp.petkind); printf("%s the %s ", temp.petkind, temp.petname); if (InTree(&temp, pt)) printf("is a member.\n"); else printf("is not a member .\n"); } void droppet(Tree * pt) { Item temp; if (TreeIsEmpty(pt)) { puts("No entries!"); return; } puts("Please enter name of pet you wish to delete: "); gets(temp.petname); puts("Please enter pet dind: "); gets(temp.petkind); uppercase(temp.petname); uppercase(temp.petkind); printf("%s the %s ", temp.petname, temp.petkind); if (DeleteItem(&temp, pt)) printf("is dropped from the club.\n"); else printf("is not a member.\n"); } void uppercase(char * str) { while (*str) { *str = toupper(*str); str++; } } int ListItemCount(Node * root) { static int conut = 0; if (root != NULL) { ListItemCount(root->left); conut += root->list_size; ListItemCount(root->right); } return conut; }