1.1.算法描述
Even算法的过程描述如下
(1)求出最大的活动整数m
(2)交换m和其箭头所掼向的与其相信的整数。
(3)交换所有满足p>m的整数的p的方向。
1.2.算法分析
由于每个数字还带有方向这个属性,因些需要使用自己定义数据类型。本算法中用一个结构来表示,结构有两个域,一个代表值,一个代码方向。
算法最大的难点在于,一是判断当前元素是否活动,二是需要找到最大的活动的元素。
通过试验生成过程,可以发现,其中最活跃的元素就是最大的那个元素,因为每交换一个比它小的元素,它都会由不活动状态变成活动状态。因此,在算法的实现上,要格外关注最大的那个元素。事实上,整个算法主要是在将最大的那个元素进行移动。也对最大的那个元素的位置进行了标识。
判断当前元素是否活动,有三种情况是不活动的:
1. 该元素在第一位,并且指向左边。
2. 该元素在最后一位,并且指向右边。
3. 该元素在中间,并且指向的元素比它要大。
通过这三个条件,就可判断当前元素是否活动的。
考虑扩展性,可排列的元素可以不从0开始,也可以不连续。因为排列归根结底是对元素的下标进行排列。因些可考虑让用户自己定义打印算法。
1#ifndef U8
2#define U8 unsigned char
3#endif // U8
4
5#define DIR_LEFT 0 // 箭头向左
6#define DIR_RIGHT 1 // 箭头向右
7
8// 用于输出 一个排列
9typedef void(*AdjustCallback)(void *const, int size);
10
11// 一个排列列的元素,它包括数字和这个数字上箭头的方向
12typedef struct Item
13{
14 int num;
15 U8 direct;
16};
17
18// 默认输出排列的函数
19void def_printarray(void *const array, int size)
20{
21 if(array == NULL)
22 return;
23 for(int i=0;i<size;i++)
24 {
25 cout<<((Item **)array)[i]->num<<' ';
26 }
27 cout<<endl;
28}
29
30// 用Even方法生成排列的类
31class Even
32{
33private:
34 Item **array; // 一队排列数
35 int size; // 排列数,表明是几排列。如5排列
36private:
37 void initarray(); // 初始化排列
38 void deletearray(); // 删除排列的元素
39 void printarray(); // 打印排列元素
40 U8 isMaxActive(Item *item); // 判断最大的元素是否活动
41 U8 isItemActive(int index); // 判断当前元素是否活动
42 U8 forward(int index); // 数列元素的一次交换,它是将当前元素与前面(或后面)的元素进行交换,具体根据箭头来判断
43 void swap(Item **p1, Item **p2); // 具体的交换操作
44 int getMaxActiveIndex(); // 获取数列中,最大的活动的元素
45 void adjustPrimar(int index); // 将比当前元素大的元素的方向换向
46public:
47 Even();
48 Even(int size);
49 virtual ~Even();
50 void gen(); // 产生排列的主函数
51 inline int getsize()const;
52 inline void setsize(int size);
53
54 AdjustCallback _printarray; // 打印数列的回调函数,支持用户自定义
55};
56
57Even::Even()
58{
59 array = NULL;
60 size = 0;
61 _printarray = &def_printarray;
62}
63
64Even::Even(int size)
65{
66 array = NULL;
67 this->size = size;
68 _printarray = &def_printarray;
69}
70
71Even::~Even()
72{
73 //
74}
75
76int Even::getsize()const
77{
78 return size;
79}
80
81void Even::setsize(int size)
82{
83 deletearray();
84 this->size = size;
85}
86
87void Even::printarray()
88{
89 if(array == NULL)
90 return;
91 for(int i=0;i<size;i++)
92 {
93 cout<<array[i]->num<<' ';
94 }
95 cout<<endl;
96}
97
98void Even::deletearray()
99{
100 if(array == NULL)
101 return;
102
103 for(int i=0;i<size;i++)
104 delete array[i];
105 delete []array;
106 array = NULL;
107}
108
109void Even::initarray()
110{
111 if(size <= 0)
112 return;
113
114 deletearray();
115
116 array = new Item* [size];
117 Item *curr;
118
119 //
120 for(int i=0;i<size;i++)
121 {
122 curr = new Item; //(Item *)malloc(sizeof(curr));
123 curr->num = i;
124 curr->direct = 0; //<-
125 array[i] = curr;
126 }
127}
128
129void Even::gen()
130{
131 if(size <= 0)
132 return;
133 initarray();
134
135 Item &max = *(array[size - 1]);
136 int currindex = size - 1;
137 int activeindex = -1;
138 U8 dir;
139
140 //printarray();
141 _printarray(array, size);
142 do{
143 //
144 while(isMaxActive(&max))
145 {
146 //exchange
147 dir = forward(currindex);
148 //printarray();
149 _printarray(array, size);
150 // adjust
151 if(dir == DIR_LEFT)
152 currindex--;
153 else currindex++;
154 }
155
156 //
157 activeindex = getMaxActiveIndex();
158 if(activeindex == -1)
159 break;
160
161 dir = forward(activeindex);
162
163 //
164 if(dir == DIR_LEFT)
165 activeindex--;
166 else activeindex++;
167 adjustPrimar(activeindex);
168 //printarray();
169 _printarray(array, size);
170
171 }while(activeindex != -1);
172}
173
174U8 Even::isMaxActive(Item *item)
175{
176 return (item->direct == DIR_LEFT && (item != array[0])) ||
177 (item->direct == DIR_RIGHT && (item != array[size - 1]));
178}
179
180U8 Even::isItemActive(int index)
181{
182 if(index == 0 && array[index]->direct == DIR_LEFT)
183 return 0;
184 else if(index == size-1 && array[index]->direct == DIR_RIGHT)
185 return 0;
186 if(array[index]->direct==DIR_LEFT && array[index] > array[index-1])
187 return 1;
188 if(array[index]->direct==DIR_RIGHT && array[index] > array[index+1])
189 return 1;
190 return 0;
191}
192U8 Even::forward(int index)
193{
194 Item *item = array[index];
195 if(item->direct == DIR_LEFT && index > 0)
196 {
197 swap(&array[index], &array[index - 1]);
198 return DIR_LEFT;
199 }
200 else if(item->direct == DIR_RIGHT && index < size - 1)
201 {
202 swap(&array[index], &array[index + 1]);
203 return DIR_RIGHT;
204 }
205 return 0;
206}
207
208void Even::swap(Item **p1, Item **p2)
209{
210 Item *tmp = *p2;
211 *p2 = *p1;
212 *p1 = tmp;
213}
214
215int Even::getMaxActiveIndex()
216{
217 int index = -1;
218 Item *currmax = NULL;
219 for(int i=0;i<size;i++)
220 {
221 if(isItemActive(i) && (currmax == NULL || currmax->num < array[i]->num))
222 {
223 index = i;
224 currmax = array[i];
225 }
226 }
227 return index;
228}
229
230void Even::adjustPrimar(int index)
231{
232 for(int i=0;i<size;i++)
233 {
234 if(i==index) continue;
235 if(array[i]->num > array[index]->num)
236 array[i]->direct = (array[i]->direct == DIR_LEFT? DIR_RIGHT:DIR_LEFT);
237 }
238}
239
240void test1();
241void test2();
242void my_printarray(void *const array, int size);
243
244int main(int argc, char *argv[])
245{
246/* int size, selcount;
247 cin>>size;
248 if (size <= 2)
249 return -1;
250
251 Even e;
252 e.setsize(size);
253 e.gen();
254 */
255// test1();
256 test2();
257 system("PAUSE");
258 return 0;
259}
260
261void test1()
262{
263 cout<<"请输入排列的阶数:";
264 int size, selcount;
265 cin>>size;
266 if (size <= 2)
267 return;
268
269 Even e;
270 e.setsize(size);
271 e.gen();
272}
273
274int arrTarget[] = {12, 9, 55, 34, 1};
275void test2()
276{
277 cout<<"原数列为:";
278 for(int i=0;i<sizeof(arrTarget)/sizeof(int);i++)
279 cout<<arrTarget[i]<<",";
280 cout<<endl;
281
282 Even e;
283 e.setsize(5);
284 e._printarray = &my_printarray;
285 e.gen();
286 cout<<endl;
287}
288
289void my_printarray(void *const array, int size)
290{
291 int index;
292 for(int i=0;i<size;i++)
293 {
294 index = ((Item **)array)[i]->num;
295 cout<<arrTarget[index]<<' ';
296 }
297 cout<<endl;
298}
2#define U8 unsigned char
3#endif // U8
4
5#define DIR_LEFT 0 // 箭头向左
6#define DIR_RIGHT 1 // 箭头向右
7
8// 用于输出 一个排列
9typedef void(*AdjustCallback)(void *const, int size);
10
11// 一个排列列的元素,它包括数字和这个数字上箭头的方向
12typedef struct Item
13{
14 int num;
15 U8 direct;
16};
17
18// 默认输出排列的函数
19void def_printarray(void *const array, int size)
20{
21 if(array == NULL)
22 return;
23 for(int i=0;i<size;i++)
24 {
25 cout<<((Item **)array)[i]->num<<' ';
26 }
27 cout<<endl;
28}
29
30// 用Even方法生成排列的类
31class Even
32{
33private:
34 Item **array; // 一队排列数
35 int size; // 排列数,表明是几排列。如5排列
36private:
37 void initarray(); // 初始化排列
38 void deletearray(); // 删除排列的元素
39 void printarray(); // 打印排列元素
40 U8 isMaxActive(Item *item); // 判断最大的元素是否活动
41 U8 isItemActive(int index); // 判断当前元素是否活动
42 U8 forward(int index); // 数列元素的一次交换,它是将当前元素与前面(或后面)的元素进行交换,具体根据箭头来判断
43 void swap(Item **p1, Item **p2); // 具体的交换操作
44 int getMaxActiveIndex(); // 获取数列中,最大的活动的元素
45 void adjustPrimar(int index); // 将比当前元素大的元素的方向换向
46public:
47 Even();
48 Even(int size);
49 virtual ~Even();
50 void gen(); // 产生排列的主函数
51 inline int getsize()const;
52 inline void setsize(int size);
53
54 AdjustCallback _printarray; // 打印数列的回调函数,支持用户自定义
55};
56
57Even::Even()
58{
59 array = NULL;
60 size = 0;
61 _printarray = &def_printarray;
62}
63
64Even::Even(int size)
65{
66 array = NULL;
67 this->size = size;
68 _printarray = &def_printarray;
69}
70
71Even::~Even()
72{
73 //
74}
75
76int Even::getsize()const
77{
78 return size;
79}
80
81void Even::setsize(int size)
82{
83 deletearray();
84 this->size = size;
85}
86
87void Even::printarray()
88{
89 if(array == NULL)
90 return;
91 for(int i=0;i<size;i++)
92 {
93 cout<<array[i]->num<<' ';
94 }
95 cout<<endl;
96}
97
98void Even::deletearray()
99{
100 if(array == NULL)
101 return;
102
103 for(int i=0;i<size;i++)
104 delete array[i];
105 delete []array;
106 array = NULL;
107}
108
109void Even::initarray()
110{
111 if(size <= 0)
112 return;
113
114 deletearray();
115
116 array = new Item* [size];
117 Item *curr;
118
119 //
120 for(int i=0;i<size;i++)
121 {
122 curr = new Item; //(Item *)malloc(sizeof(curr));
123 curr->num = i;
124 curr->direct = 0; //<-
125 array[i] = curr;
126 }
127}
128
129void Even::gen()
130{
131 if(size <= 0)
132 return;
133 initarray();
134
135 Item &max = *(array[size - 1]);
136 int currindex = size - 1;
137 int activeindex = -1;
138 U8 dir;
139
140 //printarray();
141 _printarray(array, size);
142 do{
143 //
144 while(isMaxActive(&max))
145 {
146 //exchange
147 dir = forward(currindex);
148 //printarray();
149 _printarray(array, size);
150 // adjust
151 if(dir == DIR_LEFT)
152 currindex--;
153 else currindex++;
154 }
155
156 //
157 activeindex = getMaxActiveIndex();
158 if(activeindex == -1)
159 break;
160
161 dir = forward(activeindex);
162
163 //
164 if(dir == DIR_LEFT)
165 activeindex--;
166 else activeindex++;
167 adjustPrimar(activeindex);
168 //printarray();
169 _printarray(array, size);
170
171 }while(activeindex != -1);
172}
173
174U8 Even::isMaxActive(Item *item)
175{
176 return (item->direct == DIR_LEFT && (item != array[0])) ||
177 (item->direct == DIR_RIGHT && (item != array[size - 1]));
178}
179
180U8 Even::isItemActive(int index)
181{
182 if(index == 0 && array[index]->direct == DIR_LEFT)
183 return 0;
184 else if(index == size-1 && array[index]->direct == DIR_RIGHT)
185 return 0;
186 if(array[index]->direct==DIR_LEFT && array[index] > array[index-1])
187 return 1;
188 if(array[index]->direct==DIR_RIGHT && array[index] > array[index+1])
189 return 1;
190 return 0;
191}
192U8 Even::forward(int index)
193{
194 Item *item = array[index];
195 if(item->direct == DIR_LEFT && index > 0)
196 {
197 swap(&array[index], &array[index - 1]);
198 return DIR_LEFT;
199 }
200 else if(item->direct == DIR_RIGHT && index < size - 1)
201 {
202 swap(&array[index], &array[index + 1]);
203 return DIR_RIGHT;
204 }
205 return 0;
206}
207
208void Even::swap(Item **p1, Item **p2)
209{
210 Item *tmp = *p2;
211 *p2 = *p1;
212 *p1 = tmp;
213}
214
215int Even::getMaxActiveIndex()
216{
217 int index = -1;
218 Item *currmax = NULL;
219 for(int i=0;i<size;i++)
220 {
221 if(isItemActive(i) && (currmax == NULL || currmax->num < array[i]->num))
222 {
223 index = i;
224 currmax = array[i];
225 }
226 }
227 return index;
228}
229
230void Even::adjustPrimar(int index)
231{
232 for(int i=0;i<size;i++)
233 {
234 if(i==index) continue;
235 if(array[i]->num > array[index]->num)
236 array[i]->direct = (array[i]->direct == DIR_LEFT? DIR_RIGHT:DIR_LEFT);
237 }
238}
239
240void test1();
241void test2();
242void my_printarray(void *const array, int size);
243
244int main(int argc, char *argv[])
245{
246/* int size, selcount;
247 cin>>size;
248 if (size <= 2)
249 return -1;
250
251 Even e;
252 e.setsize(size);
253 e.gen();
254 */
255// test1();
256 test2();
257 system("PAUSE");
258 return 0;
259}
260
261void test1()
262{
263 cout<<"请输入排列的阶数:";
264 int size, selcount;
265 cin>>size;
266 if (size <= 2)
267 return;
268
269 Even e;
270 e.setsize(size);
271 e.gen();
272}
273
274int arrTarget[] = {12, 9, 55, 34, 1};
275void test2()
276{
277 cout<<"原数列为:";
278 for(int i=0;i<sizeof(arrTarget)/sizeof(int);i++)
279 cout<<arrTarget[i]<<",";
280 cout<<endl;
281
282 Even e;
283 e.setsize(5);
284 e._printarray = &my_printarray;
285 e.gen();
286 cout<<endl;
287}
288
289void my_printarray(void *const array, int size)
290{
291 int index;
292 for(int i=0;i<size;i++)
293 {
294 index = ((Item **)array)[i]->num;
295 cout<<arrTarget[index]<<' ';
296 }
297 cout<<endl;
298}