题目. 使用gcc编译,所提供的必须是可输出正确结果的程序
1.允许两个操作,add(min,max)和del(min,max),一开始区间内为空,每个操作后算出区间内的集合,要求能自动合并、拆分集合。例如:
操作1:add(1,7) 区间内的集合:(1,7)
操作2:add(9,10) 区间内的集合:(1,7)、(9,10)
操作3:del(3,5) 区间内的集合:(1,2)、(6,7)、(9,10)
操作4:add(3,8) 区间内的集合:(1,10)
整个区间的范围可能会在(0,2^32-1)之间。
要求给出add()和del()的算法描述和代码实现,程序要实现输入输出即可供用户操作。
以下是我自己写的代码:
main.c
/*
* Copyright(C) 2010 XXXXX. All rights reserved.
*/
/*
* main.c
* Original Author: syijin@163.com 2010-08-19
*/
#include <stdio.h>
#include <string.h>
#include "List.h"
#include "qujian.h"
struct list_head *head;
int main(void)
{
uint min, max;
char text[10], str[5];
LIST_HEAD(qujian_head);
qujian_t qjt_head;
head = &qujian_head;
qjt_head.node = qujian_head;
printf("Exit with 'end'!/n");
while (1) {
printf("Please input 'a min max' or 'd min max':");
gets(text);
sscanf(text, "%2s%u%u", str, &min, &max);
if (str[0] == 'e') {
break;
}
if (min > max) {
printf("Input error!/n");
continue ;
}
if (str[0] == 'a') {
add(min, max);
} else if (str[0] == 'd') {
del(min, max);
}
ceshi_travle(head);
}
travle(head);
return 0;
}
qujian.h
#ifndef _QUJIAN_H_
#define _QUJIAN_H_
#include "list.h"
extern struct list_head *head;
typedef unsigned int uint;
typedef struct {
uint min;
uint max;
struct list_head node;
} qujian_t;
struct list_head *new_qj(uint min, uint max, struct list_head *pos);
void add(uint min, uint max);
void hebing(struct list_head *start);
void travle(struct list_head *head);
void del(uint min, uint max);
void ceshi_travle(struct list_head * head);
#endif
qujian.c
#include <malloc.h>
#include <stdio.h>
#include "list.h"
#include "qujian.h"
/* 申请一个qujian_t空间,并插到pos后面,返回新节点的指针 */
struct list_head *new_qj(uint min, uint max, struct list_head *pos)
{
qujian_t *p_qj;
p_qj = (qujian_t *)malloc(sizeof(qujian_t));
if (p_qj == NULL) {
perror("malloc qujian_t error");
return NULL;
}
p_qj->min = min;
p_qj->max = max;
list_add(&p_qj->node, pos);
return &p_qj->node;
}
/* 添加一个新的区域 */
void add(uint min, uint max)
{
struct list_head *new;
qujian_t *pos;
list_for_each_entry(pos, head, node, qujian_t) {
if (min < pos->min) {
new = new_qj(min, max, (&pos->node)->prev);
hebing(new);
return ;
} else if (min <= pos->max +1) { /* (1,7) (8,9); 因此要+1 */
pos->max = (pos->max >= max)? pos->max : max;
hebing(&pos->node);
return ;
}
}
new_qj(min, max, head->prev); /* 插到最后 */
return ;
}
/* 判断start后面的区域是否与start重合,重合则合并 */
void hebing(struct list_head *start)
{
uint max;
struct list_head *n, *new;
qujian_t *pos, *temp;
temp = list_entry(start, qujian_t, node);
max = temp->max;
new = start;
/* 此处不能用list_head中的循环, 因为不是从head开始遍历的 */
for (pos = list_entry((start)->next, qujian_t, node), n = pos->node.next;
&pos->node != (head);
pos = list_entry(n, qujian_t, node), n = pos->node.next) {
if (max < pos->min - 1) { /* 如(3,5) (1,2); 相等和差1归到下一种情况 */
break;
} else if (max <= pos->max) {
(list_entry(new, qujian_t, node))->max = pos->max;
list_del(n->prev);
free(pos);
break;
} else {
list_del(&pos->node);
free(pos);
}
}
return ;
}
/* 删除区间(min, max) */
void del(uint min, uint max)
{
struct list_head *n;
qujian_t *pos;
add(min, max); /* 把要删除的区间先加入,这样min, max只会在同一个区间中 */
list_for_each_entry_safe(pos, n, head, node, qujian_t) {
if (min == pos->min && max == pos->max) {
list_del(&(pos->node));
free(pos);
return ;
} else if (min == pos->min) {
pos->min = max + 1;
return ;
} else if (max == pos->max) {
pos->max = min -1;
return ;
} else if (min > pos->min && max < pos->max) {
new_qj(max + 1, pos->max, &pos->node); /* 注意顺序,应在pos->max = min -1;之前 */
pos->max = min -1;
return ;
}
}
return ;
}
/* 遍历并释放空间 */
void travle(struct list_head *head)
{
qujian_t *pos;
struct list_head *n;
list_for_each_entry_safe(pos, n, head, node, qujian_t) {
printf("(%u,%u)", pos->min, pos->max);
list_del(&(pos->node));
free(pos);
}
return ;
}
ceshi.c
#include <stdio.h>
#include "qujian.h"
/* just travle */
void ceshi_travle(struct list_head *head)
{
qujian_t *pos;
struct list_head *n;
list_for_each_entry_safe(pos, n, head, node, qujian_t) {
printf("(%u,%u)", pos->min, pos->max);
}
printf("/n");
return ;
}
lish.h在我的文章“双向链表操作“