题目
奇偶排序及其并行化设计
定义
奇偶排序法的思路是在数组中重复两趟扫描。第一趟扫描选择所有的数据项对,a[j]和a[j+1],j是奇数(j=1, 3, 5……)。如果它们的关键字的值次序颠倒,就交换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=0,2, 4,6……)。重复进行这样两趟的排序直到数组全部有序。
奇偶交换总是成对出现,这样才能保证比较和交换涉及到数组中的每一个元素。
分析
奇偶排序可以看做是冒泡排序的升级版,但冒泡排序中每个元素既可能与前面的元素交换,也可能与后面的元素交换,奇偶排序消除了这种数据的相关性,所以可以实现并行化设计。
#include "pch.h" #include <iostream> #include "stdio.h" #include "omp.h" using namespace std; int main() { bool flag = true,change=true; int n; cin >> n; int *a =new int[n]; for (int i = 0; i < n; i++) { cin >> a[i]; } //设定并行线程数 omp_set_num_threads(n / 2); //flag为true或者 change为false(即要进行奇排序时)进入循环 while (flag || !change) { flag = false; if (change) //偶循环 { //并行for开始 #pragma omp parallel for for (int i = 0; i < n-1; i += 2) { if (a[i] > a[i + 1]) { flag = true; int temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; } } } else //奇循环 { //并行for开始 #pragma omp parallel for for (int i = 1; i < n-1; i += 2) { if (a[i] > a[i + 1]) { flag = true; int temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; } } } //奇变偶 偶变奇 if (change) { change = false; } else { change = true; } } for (int i = 0; i < n; i++) { cout<<a[i]<<" "; } return 0; }
注意细节,假如上一轮发生数据交换或者变为奇排序,则继续循环。
发生数据交换进入循环很好理解。
奇循环条件,则是因为一开始进行的是偶循环,为了保证可以进行一轮偶循环和奇循环之后才结束,因为不存在一个数列,奇循环和偶循环都不发生数据交换的情况下是乱序。
但是存在数列,偶循环下不发生数据交换,奇循环下发生数据循环。[1,2,1,2,1,2]就是,现在是乱序的。
最近上课发现可以在一轮里面同时进行奇偶排序就行可以简化代码
int main() { bool flag = true; int n; cin >> n; int *a =new int[n]; for (int i = 0; i < n; i++) { cin >> a[i]; } //设定并行线程数 omp_set_num_threads(n / 2); //flag为true或者 change为false(即要进行奇排序时)进入循环 while (flag) { flag = false; //并行for开始 #pragma omp parallel for for (int i = 0; i < n-1; i += 2) { if (a[i] > a[i + 1]) { flag = true; int temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; } } //并行for开始 #pragma omp parallel for for (int i = 1; i < n-1; i += 2) { if (a[i] > a[i + 1]) { flag = true; int temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; } } } for (int i = 0; i < n; i++) { cout<<a[i]<<" "; } return 0; }