数据结构-使用数组作为环

来源:互联网 发布:广电网络套餐资费表 编辑:程序博客网 时间:2024/06/15 06:07

使用数组作为环

综述
环是一种比较复杂的数据结构,能够处理需要重复执行从头到尾循环的逻辑。但是环写起来比较让人费解,不易于维护。如果用相对简单的数组来代替环进行处理,效果会好很多。

需求
有这么一个需求:有一个活动,一个星期内任意几天开启,每次开启都是在每天的0点到24点之间的任意一个时间段。一个活动结束后需要获得下一个活动的开启的倒计时。

解答思路
率先找到该结束活动的第一个相邻的开启的活动,取开启时间与当前时间之差,即是倒计时。需要注意的是,当一个星期的最后一次活动结束,则需要回到星期开始的时候重新计算。这时候就需要用到一个环。

解答1

 1 #include <stdio.h>  2    3 struct loop {  4     int data;                                                                                                                                                                              5     struct loop* next;  6 };  7    8 int main(int argc, char* argv[])  9 { 10     struct loop act[3]; 11   12     struct loop head; 13     head.data = 2; 14     head.next = NULL; 15   16     act[0].data = head.data; 17     act[0].next = head.next; 18   19     struct loop node1; 20     node1.data = 4; 21     node1.next = NULL; 22     act[0].next = &act[1]; 23   24     act[1].data = node1.data; 25     act[1].next = node1.next; 26   27     struct loop end; 28     end.data = 6; 29     end.next = NULL; 30     act[1].next = &act[2]; 31   32     act[2].data = end.data; 33     act[2].next = end.next; 34   35     act[2].next = &act[0]; 36   37     struct loop* temp = &act[0]; 38     /* 39     while(temp->next) { 40         printf("data : %d\n", temp->data); 41         temp = temp->next; 42     } 43     */ 44   45     int act_num = 0; 46     printf("Enter Act Num : "); 47     scanf("%d", &act_num); 48   49     if (act_num > 2 || act_num < 0) { 50         printf("[Error] Act Num in [0,2]\n"); 51         return -1; 52     } 53   54     temp = &act[act_num]; 55     temp = temp->next; 56   57     printf("The Next Act of Num%d Act is %d\n", act_num, temp->data); 58   59   60     return 0; 61 }

上述方法采用了一个最简单环的方式解决问题,优点是简单明了,但是缺点是需要维护一个环,确保指向的正确。

解答二

 759 uint32_t TimeTowerConfig::get_countdown_by_id(uint32_t id, uint32_t valid_times) 760 { 761     time_tower_time_t* tttt = get_time_tower_time(id);  762     if (!tttt) {           763         KERROR_LOG(0, "TIME TOWER CONFIG GET TIME ERROR ID %u", id); 764         return 10000;      765     } 766   767     //[0]获得今天是星期几  768     struct tm data;        769     taotao_serv_util::get_data(data); 770     int week_day = data.tm_wday; 771     if (week_day == 0) {   772         week_day = 7;      773     } 774   775     //[1]创建一个15长度的数组,代表2个星期,即一个环(0作废) 776     int loop[15] = {0};    777     for (int i = 0; i < 15; ++i) {   778         loop[i] = 0;       779     } 780   781     //[2]获取开放的星期    782     for (size_t i = 0; i < tttt->weekdays.size(); ++i) {  783         uint32_t day = tttt->weekdays[i]; 784         if (day == 0) {    785             day = 7;       786         } 787         //预防策划表配错数组越界 788         if (day > 7) {     789             KERROR_LOG(0, "TIME TOWER GET COUNTDOWN WEEKDAYS ERROR %u", day); 790             break;         791         }           792   793         loop[day]     = 1; 794         loop[day + 7] = 1; 795     } 796   797     //[3]确定今天是否还有开放 798     //开始小时 799     uint32_t start_hour = tttt->start_hour; 800     //结束小时 801     uint32_t end_hour   = tttt->end_hour; 802     //当前时间 803     uint32_t time_now   = get_now_tv()->tv_sec; 804     //零点时间 805     uint32_t time_zero  = taotao_serv_util::get_start_of_day(); 806     //开始时间 807     uint32_t time_start = time_zero + start_hour * 60 * 60; 808     //结束时间 809     uint32_t time_end   = time_zero + end_hour * 60 *60; 810   811     //如果今天不能开放则明天开放 812     uint32_t end_flag = 0; 813     if (time_now >= time_end) { 814         week_day = week_day + 1; 815     //如果在开放时间内,但剩余次数为0的情况,则需要在明天开启 816     } else if (time_start <= time_now && time_now <= time_end) { 817         if (!valid_times) { 818             week_day = week_day + 1; 819             end_flag = 1; 820         } 821     } 822   823     //[3]获取最近开放的星期 824     int last_open_day = week_day; 825     for (int i = week_day; i < 15; ++i) { 826         if (loop[i]) { 827             last_open_day = i; 828             break; 829         } 830     } 831   832     //间隔时间 833     int interval_day = 0;                                                                                                                                                                834     interval_day = last_open_day - week_day;  835   836     //倒计时 837     uint32_t countdown = 0; 838     //[1]如果开始时间大于当前时间 839     if (time_end >= time_now) { 840         if (end_flag) { 841             interval_day = interval_day + 1; 842         } 843         countdown = time_end + interval_day * DAY_ONE - time_now; 844     } else { 845         countdown = time_end + (interval_day + 1) * DAY_ONE - time_now; 846     } 847   848     return countdown; 849 }

解读

如果只需要使用一次环,可以一个长度为N数组维护的内容复制一份出来,拼接在数组后面,这样从N+1读下去到2N相当于遍历了一遍环。
优点是简洁明了,缺点是需要复制一份数据,在数据量较大时候会消耗较多内存。

0 0