标签:c primer plus (第五版) 第十七章 高级数据显示 编程练习
修改程序清单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;
}本文出自 “30岁学编程” 博客,请务必保留此出处http://xiongyi85.blog.51cto.com/8756903/1663789
C Primer Plus (第五版) 第十七章 高级数据显示 编程练习
标签:c primer plus (第五版) 第十七章 高级数据显示 编程练习
原文地址:http://xiongyi85.blog.51cto.com/8756903/1663789