您的位置:首页 > 理论基础 > 数据结构算法

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

2015-11-27 14:58 344 查看

使用数组作为环

综述

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

需求

有这么一个需求:有一个活动,一个星期内任意几天开启,每次开启都是在每天的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相当于遍历了一遍环。

优点是简洁明了,缺点是需要复制一份数据,在数据量较大时候会消耗较多内存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: