vector删除偶数算法。

电话面试遇到一个题目,删除所有的偶数。

 

先上代码。

  1 #include <vector>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <stdlib.h>
  5 
  6 #define IS_EVEN(a) (0 == (a) % 2)
  7 #define IS_ODD(a) (0 != (a) % 2)
  8 
  9 bool isEven(unsigned int a)
 10 {
 11     return !(a % 2);
 12 }
 13 
 14 int main(int argc, char** argv)
 15 
 16 {
 17     if (argc < 3)
 18     {
 19         std::cout << "\n==================================================="
 20                   << "\n" << argv[0] << "        [size][alog][y/n])]"
 21                   << "\n size:         acount of numbers"
 22                   << "\n alog:        algorithm 1.common loop 2. exchange and move if not delete from end  3. exchange and never move"
 23                   << "\n numberstput:    \'y\' to numberstput result"
 24                   << "\n===================================================\n";
 25     }
 26     int VEC_SIZE = atoi(argv[1]);
 27     int head = 0, tail = VEC_SIZE - 1;
 28 
 29     // init data
 30     std::vector<int> numbers(VEC_SIZE);
 31     for (int i = 0; i < VEC_SIZE; i++)
 32     {
 33         numbers.at(i) = (int)(rand() % (VEC_SIZE * 10));
 34     }
 35 
 36     if (argc > 3 && 'y' == *argv[3])
 37     {
 38         std::cout << "\n============================= before ===========================\n";
 39         tail = numbers.size() ;
 40         for (int i = 0; i < tail; i++)
 41                 std::cout <<  numbers.at(i) << " ";
 42     }
 43 
 44     if ('1' == *argv[2])
 45     {    
 46         // algo 1: loop common.  stable.
 47         for (int i = 0; i < numbers.size();)
 48         {
 49             if (numbers[i] % 2 == 0)
 50                 numbers.erase(numbers.begin() + i);
 51             else
 52                 ++i;
 53         }
 54     }
 55 
 56 
 57     else if ('2' == *argv[2])
 58     {
 59         // will trigger memory movement if no delete from end. not stable
 60         for(; head <= tail;)
 61         {
 62             // odd - even
 63             if (IS_ODD(numbers[head]) && IS_EVEN(numbers[tail]))
 64             {
 65                 numbers.erase(numbers.begin() + tail);
 66                 --tail;
 67                 ++head;
 68             }
 69             // even - odd
 70             else if (IS_EVEN(numbers[head]) && IS_ODD(numbers[tail]))
 71             {
 72                 numbers[head] = numbers[tail];
 73                 numbers.erase(numbers.begin() + tail);
 74                 ++head;
 75                 --tail;
 76             }
 77             // odd - odd
 78             else if (IS_ODD(numbers[head]) && IS_ODD(numbers[tail]))
 79             {
 80                 ++head;
 81                 --tail;
 82             }
 83             // even-even
 84             else if (IS_EVEN(numbers[head]) && IS_EVEN(numbers[tail]))
 85             {
 86                 numbers.erase(numbers.begin() + tail);
 87                 --tail;
 88             }
 89         }
 90     }
 91 
 92     else if ('3' == *argv[2])
 93     {
 94         // always delete from end, never trigger memory movement. not stable
 95         for(; head <= tail;)
 96         {
 97             // odd - even
 98             if (IS_ODD(numbers[head]) && IS_EVEN(numbers[tail]))
 99             {
100                 numbers[tail] = *numbers.rbegin();
101                 numbers.pop_back();
102                 
103                 --tail;
104                 ++head;
105             }
106             // even - odd
107             else if (IS_EVEN(numbers[head]) && IS_ODD(numbers[tail]))
108             {
109                 numbers[head] = *numbers.rbegin();
110                 numbers.pop_back();
111 
112                 ++head;
113                 --tail;
114             }
115             // odd - odd
116             else if (IS_ODD(numbers[head]) && IS_ODD(numbers[tail]))
117             {
118                 ++head;
119                 --tail;
120             }
121             // even - even
122             else if (IS_EVEN(numbers[head]) && IS_EVEN(numbers[tail]))
123             {
124                 numbers[tail] = *numbers.rbegin();
125                 numbers.pop_back();
126                 --tail;
127             }
128         }
129     }
130 
131     else if ('4' == *argv[2])
132     {
133         // always overide even with a adjacent odd. stable
134         head = 0, tail = 1;
135         for(;tail < VEC_SIZE;)
136         {
137             if (IS_EVEN(numbers[head]) && IS_ODD(numbers[tail]))
138             {
139                 numbers[head] = numbers[tail];
140                 numbers[tail] = 0; // make it as a EVEN.
141                 ++head;
142                 ++tail;
143             }
144             else if (IS_ODD(numbers[head]) && IS_EVEN(numbers[tail]))
145             {                
146                 ++head;
147                 ++tail;
148             }
149             else if (IS_EVEN(numbers[head]) && IS_EVEN(numbers[tail]))
150             {
151                 ++tail;
152             }
153             else if (IS_ODD(numbers[head]) && IS_ODD(numbers[tail]))
154             {
155                 head+=2;
156                 tail+=2;
157             }
158         }
159         // erase all the unused number from head.
160         numbers.erase(numbers.begin()+head, numbers.end());
161     }
162 
163     else if ('5' == *argv[2])
164     {
165         //call remove_if
166         std::vector<int>::iterator tail = remove_if(numbers.begin(), numbers.end(), isEven);
167         numbers.erase(tail, numbers.end());
168     }
169 
170     if (argc > 3 && 'y' == *argv[3])
171     {
172         std::cout << "\n============================= after ===========================\n";
173         tail = numbers.size() ;
174         for (int i = 0; i < tail; i++)
175                 std::cout <<  numbers.at(i) << " ";
176     }
177 }

 

测试环境:i7-6600U 8G RAM 

分支1: 菜鸡强撸,数据量10w 大约60秒+, 100w好久都跑不出结果

分支2,两端向中间扫描,奇数替换偶数,不从末尾删除会导致memory move。非稳定算法,删除后,item顺序乱掉。

分支3,同2,不同在于一直从末尾删除,不触发memory move。非稳定算法,删除后,item顺序乱掉。

分支4,从开头扫描每次扫描两个item,奇数替换偶数,不触发memory move。 稳定算法。

分支5,调用STL 算法

 

事实证明STL的remove_if的原理和分支4一致。

同样开启-O3优化选项。

1billion数据量,处理时间均在1.6 second左右。

为了最大限度模拟生产环境,数据初始化用了随机数。 此种情况下,分支4和STL 速度一致。

如果用下标初始化每个item。STL在1.4秒左右处理 1billion。  比分支4快15%左右。maybe此种情况下编译器有特殊优化。不得而知。

 

posted @ 2017-04-25 13:33  dfdqzp  阅读(791)  评论(0编辑  收藏  举报