(一)问题描述:
由键盘随机输入若干个整数,设计程序输出给定的整数并统计每个整数出现的频次(相同的不重复记录,模拟建立文章单字索引表)
(二)算法分析:
本题的目的是让读者掌握动态分配空间函数 malloc 的应用以及创建链表的方法。
链表有若干个结点按一定规律连接而成,只有通过前一个结点才能找到后一个结点。用结构体变量和指针并结合动态存储分配函数就可以建立链表,主要特点是存储数据不一定需要连续的空间,且插入元素与删除元素的效率更高。
本题需要解决以下几个问题:
(1)定义链表的结点类型。链表的结点包括整数值、频数、链接指针。
(2)将任意输入的整数记录到链表中。先查看链表有无此整数,若有,只需将此整数对应的结点的出现频数加1即可;若无,就将此数插入到链表中,也就是动态开辟一个内存空间,将此整数放入,然后将此空间的节点链接指针指向原链表的开头指针,并将此空间成为当前链表头(头插法)
(3)扫描输出链表的各个结点,也就是输出每个整数及其出现的频次。
(三)程序源码:
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct statistics)
//建立一个结构体链表,其中number表示某个数,count表示这个数出现的次数
struct statistics{
int number;
int count;
struct statistics *next;
};
struct statistics *add(int num, struct statistics *head);
void sta_print(struct statistics *head);
int main(void)
{
struct statistics *head = NULL; //链表的头
int num;
scanf("%d", &num); //读入一个整数,假如是负数就结束程序
while(num >= 0){
head = add(num, head); //链表的头按要求进行处理
scanf("%d", &num);
}
sta_print(head); //输出结果
system("pause");
return 0;
}
/*判断读入的数是否已经存在在链表中了,如果没有,在链表头插入结点*/
struct statistics *add(int num, struct statistics *head)
{
int judge = 1; //判断是否存在在链表中:1为不存在;0为存在
struct statistics *p = head;
while(p != NULL){
if(p -> number == num){
judge = 0; //这个数已经存在
break;
}
else{
p = p -> next;
}
}
//如果已经存在,就给这个数的count加上1*/
if(judge == 0){
p -> count += 1;
}
else{
//否则就在链表头插入这个数
p = head;
head = (struct statistics *) malloc (LEN);
head -> number = num;
head -> count = 1;
head -> next = p;
}
return head;
}
/*输出统计数字*/
void sta_print(struct statistics *head)
{
while(head != NULL){
printf("整数%d出现了%d次;", head -> number, head -> count);
head = head -> next;
}
return;
}
(四)插入结点方法整理:
(1)在链表头插入结点的过程如下:
1)将原来的链表头指针存放到另一个指针变量 P 中,即p = head;
2)开辟新空间赋予原来的链表头指针,即 head = (struct statistics *) malloc (LEN);
3)将新开辟的结点的链接指针指向 P ,即 head -> next = p;
(2)在链表中间的某个结点处插入一个结点过程如下:
1)将当前 P 的下一个结点存放到另一个指针变量 q ,即 q = p -> next;
2)开辟新结点 x,并让 p 指向 x,即 p -> next = x;
3)让 x 指向 q,即 x -> next = q;
(3)在链表尾部插入一个结点过程如下:
1)开辟新结点 x,并让 x 指向空,即 x -> next = NULL;
2)让尾结点 p 指向 x,即 p -> next = x;