面试题合并区间(续)

前面讲到对一系列的区间合并,里边定义了结构

1 struct myDataType
2 {
3     unsigned int a;
4     unsigned int b;
5     bool flag;
6 };

具体参考:http://www.cnblogs.com/ivorfeng/archive/2013/04/30/3052022.html

如果是对IP区间的合并呢?首先先回顾一下关于IP的知识。

一个IP地址由32bit组成,形式上为x.x.x.x,每一个x的范围是0~255,即1Byte = 8 bit。也就是说,对于每一个IP地址,我们都可以将其看成是32bit的数,对应于计算机里的unsigned int,这样我们就可以定义IP地址的数据结构为如下:

1 struct IP
2 {    //按低位向高位排
3     unsigned int p4:8;
4     unsigned int p3:8;
5     unsigned int p2:8;
6     unsigned int p1:8;
7 };

 思路:现在,我们成功地将一个IP地址对应到一个unsigned int类型的值,接下来就好办了,即将问题转化为对整数区间的合并,待输出结果时,还需要将结果转化为IP地址的形式。

实际写代码的时候,我们只需要使用合并区间 里面的myDataType这个数据结构,输入是把IP地址的值转化到myDataType里边的值即可,下面讲解如何转化。

输出的时候,将该数地址转为IP类型的地址,按IP的内容输出即可;现在的关键是如何把输入的IP,转化为unsigned int值。我们知道bit field是不支持取地址操作的,因此将myDataType类型的地址转化为IP类型的地址后,取其地址输入的办法是行不通的。但我们知道unsigned char 的字节刚好就1Byte,因此可以借助unsigned char类型的临时数组,先把IP地址的各位数输入到该数组,然后再将数据赋值到IP结构里边的值。看文字可能不太清楚,下面看看代码:

 1 int main()
 2 {    
 3     int T;
 4     printf("输入测试次数:\n");
 5     scanf("%d",&T);
 6     while(T--)
 7     {
 8         int N;
 9         printf("输入IP区间数:\n");
10         scanf("%d",&N);
11         myDataType *p = (myDataType*)malloc(N * sizeof(myDataType));
12 
13         for(int i = 0; i < N; ++i)
14         {
15             //myDataType类型的地址转化为IP类型的地址
16             IP *tmp1 = (IP *)&((p+i)->a);
17             IP *tmp2 = (IP *)&((p+i)->b);
18             //借助unsigned char类型的临时数组,先把IP地址的各位数输入到该数组
19             unsigned char ip1[4];
20             unsigned char ip2[4];
21             scanf("%d %d %d %d", ip1, ip1 + 1, ip1 + 2, ip1 + 3);
22             scanf("%d %d %d %d", ip2, ip2 + 1, ip2 + 2, ip2 + 3);
23             //将数据赋值到IP结构里边的值
24             tmp1->p1 = ip1[0];
25             tmp1->p2 = ip1[1];
26             tmp1->p3 = ip1[2];
27             tmp1->p4 = ip1[3];
28             tmp2->p1 = ip2[0];
29             tmp2->p2 = ip2[1];
30             tmp2->p3 = ip2[2];
31             tmp2->p4 = ip2[3];
32             /*scanf("%d %d",&((p+i)->a),&((p+i)->b));*/
33             (p+i)->flag = true;
34         }
35         newInterval(p, N);
36         free(p);
37         p = NULL;
38 
39     }


下面是关键函数:

 1 //判断p1  p2是否有交集
 2 bool isOverlap(myDataType *p1, myDataType *p2)
 3 {
 4     bool result = false;
 5     if(p1 == NULL || p2 == NULL)
 6         return result;
 7 
 8     if((*p1).b >= (*p2).a)
 9         result = true;
10 
11     return result;
12 }
13 //更新p1
14 void update(myDataType *p1, myDataType *p2)
15 {
16     if((*p1).b < (*p2).b)
17         (*p1).b = (*p2).b;
18 
19     if((*p1).a > (*p2).a)
20         (*p1).a = (*p2).a;
21 }
22 //比较函数 
23 int compare(const void *p1, const void *p2)
24 {
25     return ((myDataType*)p1)->a - ((myDataType*)p2)->a;
26 }
27 
28 void newInterval(myDataType *p, int nLen)
29 {
30 
31     if(p == NULL || nLen <= 0)
32         return;
33     //区间排序 
34     qsort(p, nLen, sizeof(myDataType), compare);
35     int i;
36     for(i = 1; i < nLen; ++i)
37     {     //判断区间是否重叠 
38         if(isOverlap(p + i - 1, p + i))
39         {    //更新后一个区间 
40             update(p + i , p + i - 1);
41             (p + i - 1)->flag = false;
42         }
43     }
44     printf("\n最终区间:\n");
45     for(i = 0; i < nLen; ++i)
46     {
47         if((p+i)->flag == true)
48         {
49             //将区间转化为IP结构输出
50             IP *tmp1 = (IP *)&((p+i)->a);
51             IP *tmp2 = (IP *)&((p+i)->b);
52             printf("%d.%d.%d.%d-", (tmp1->p1), (tmp1->p2), (tmp1->p3), (tmp1->p4));
53             printf("%d.%d.%d.%d\n", (tmp2->p1), (tmp2->p2), (tmp2->p3), (tmp2->p4));
54         }
55             
56     }
57     printf("\n");
58 
59 }

 下面给一个简单的例子:

原文地址:https://www.cnblogs.com/ivorfeng/p/3061137.html