POJ-1007 DNA Sorting
2014-11-17 13:12
267 查看
【题目描述】
计算每条DNA(字符串)的inversions,即按字典序,每一字符比后面字符大的数量之和。最后按inversions从小到大排序输出,相同inversions的输出原序。
【思路分析】
1. 存储结构
采用vector存储DNA字符串,并用一个二维数组sortScore[101][2],存放{inversions, id}。
2. 计算inversions
将该字符c与后面所有字符比较,计数即可。
3. 排序算法(稳定与非稳定)
首先看看稳定排序算法,即相同数值保持原序,包括:
[align=justify]冒泡:小的元素往前移动。如果某次待交换的元素相等,则不会交换,说明相同元素的顺序不会改变,故冒泡是稳定的排序算法;[/align]
[align=justify]插入:对已有序的子序列插入当前元素。如果有序子序列在最前,则从子序列末尾开始比较,将当前元素插入到第一个小于等于该元素的单元后面,这样相同元素的顺序也不会改变,故插入是稳定排序算法;[/align]
[align=justify]选择:每次选择第一个最小的元素,进行排列。这样,选择排序是稳定排序算法;[/align]
[align=justify]归并:分治方法,将序列一分为二,单独排序后进行合并。合并时,相同值的元素可以按原序进行排序,故归并也是稳定排序算法;[/align]
[align=justify]基数:按照最低位开始,排序,直到最高位。同样是相同值不改变顺序,故基数也是稳定排序;[/align]
接下来是非稳定排序算法,无法保证相同数值按照原序排列,包括:
[align=justify]快速:将当前元素(例如子序列的第一个元素),放到正确的位置,使得前面的元素比其小,后面的元素比其大。在交换时,碰到此种状况,会导致稳定性被破坏:5, 3a, 7, 4, 3b, 3c. --- 3c, 3a, 7, 4, 3b, 3c. --- 3c, 3a, 7, 4, 3b, 7. ---3c, 3a, 3b, 4, 5, 7. 故快速排序是不稳定排序;[/align]
[align=justify]堆排序:建堆的方式,1, 2a, 3, 2b,建小顶堆,2b比2a先输出,故堆排序也是不稳定的;[/align]
[align=justify]希尔排序:多次不同步长的插入排序,会破坏稳定性,故希尔是不稳定排序;[/align]
按理来说应该采用稳定的排序算法,但用快排(不稳定)也可以通过。采用快排qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) ) 该函数。按本题来说,要对二维数组进行排序,则num为二维数组的行数,size为二维数组一行的长度,故如下调用方式:
其中,比较函数需要看成是一维数组的方式进行比较,a和b看成是一维数组指针,然后对相应单元进行比较,(下面代码代表从小到大排序)则为:
【小结】
该题需要关注的重点在于:稳定与非稳定排序算法、qsort()的二维数组排序方法。
【附:完整代码】
计算每条DNA(字符串)的inversions,即按字典序,每一字符比后面字符大的数量之和。最后按inversions从小到大排序输出,相同inversions的输出原序。
【思路分析】
1. 存储结构
采用vector存储DNA字符串,并用一个二维数组sortScore[101][2],存放{inversions, id}。
2. 计算inversions
将该字符c与后面所有字符比较,计数即可。
for (int chari(0); chari < length; chari++) { char testchar = testdna[chari]; for (int charj(chari+1); charj < length; charj++) { if (testdna[charj] < testchar) sortScore[dnai][0]++; } }
3. 排序算法(稳定与非稳定)
首先看看稳定排序算法,即相同数值保持原序,包括:
[align=justify]冒泡:小的元素往前移动。如果某次待交换的元素相等,则不会交换,说明相同元素的顺序不会改变,故冒泡是稳定的排序算法;[/align]
[align=justify]插入:对已有序的子序列插入当前元素。如果有序子序列在最前,则从子序列末尾开始比较,将当前元素插入到第一个小于等于该元素的单元后面,这样相同元素的顺序也不会改变,故插入是稳定排序算法;[/align]
[align=justify]选择:每次选择第一个最小的元素,进行排列。这样,选择排序是稳定排序算法;[/align]
[align=justify]归并:分治方法,将序列一分为二,单独排序后进行合并。合并时,相同值的元素可以按原序进行排序,故归并也是稳定排序算法;[/align]
[align=justify]基数:按照最低位开始,排序,直到最高位。同样是相同值不改变顺序,故基数也是稳定排序;[/align]
接下来是非稳定排序算法,无法保证相同数值按照原序排列,包括:
[align=justify]快速:将当前元素(例如子序列的第一个元素),放到正确的位置,使得前面的元素比其小,后面的元素比其大。在交换时,碰到此种状况,会导致稳定性被破坏:5, 3a, 7, 4, 3b, 3c. --- 3c, 3a, 7, 4, 3b, 3c. --- 3c, 3a, 7, 4, 3b, 7. ---3c, 3a, 3b, 4, 5, 7. 故快速排序是不稳定排序;[/align]
[align=justify]堆排序:建堆的方式,1, 2a, 3, 2b,建小顶堆,2b比2a先输出,故堆排序也是不稳定的;[/align]
[align=justify]希尔排序:多次不同步长的插入排序,会破坏稳定性,故希尔是不稳定排序;[/align]
按理来说应该采用稳定的排序算法,但用快排(不稳定)也可以通过。采用快排qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) ) 该函数。按本题来说,要对二维数组进行排序,则num为二维数组的行数,size为二维数组一行的长度,故如下调用方式:
qsort(sortScore, num, sizeof(int)*2, CompareFunction);
其中,比较函数需要看成是一维数组的方式进行比较,a和b看成是一维数组指针,然后对相应单元进行比较,(下面代码代表从小到大排序)则为:
int CompareFunction(const void* a, const void* b) { int *pa = (int*)a; int *pb = (int*)b; return pa[0] - pb[0]; }
【小结】
该题需要关注的重点在于:稳定与非稳定排序算法、qsort()的二维数组排序方法。
【附:完整代码】
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int sortScore[101][2]; // {inversion, id}
int CompareFunction(const void* a, const void* b) { int *pa = (int*)a; int *pb = (int*)b; return pa[0] - pb[0]; }
long Partition(int arraylist[][2], int low, int high)
{
int toBePosition[2];
memcpy(toBePosition, arraylist[low], sizeof(arraylist[low]));
while (low < high)
{
while (low < high && arraylist[high][0] >= toBePosition[0])
high--;
memcpy(arraylist[low], arraylist[high], sizeof(arraylist[high]));
while (low < high && arraylist[low][0] <= toBePosition[0])
low++;
memcpy(arraylist[high], arraylist[low], sizeof(arraylist[low]));
}
memcpy(arraylist[low], toBePosition, sizeof(toBePosition));
return low;
}
void QSort(int arraylist[][2], int low, int high)
{
if (low < high)
{
long pos = Partition(arraylist, low, high);
QSort(arraylist, low, pos-1);
QSort(arraylist, pos+1, high);
}
}
int main()
{
int length, num;
cin>>length>>num;
vector<string> DNAs;
memset(sortScore, 0, sizeof(sortScore));
for (int i(0); i < num; i++)
{
string tempstr;
cin>>tempstr;
DNAs.push_back(tempstr);
sortScore[i][0] = 0;
sortScore[i][1] = i;
}
// 计算每个DNA的inversion
for (int dnai(0); dnai < num; dnai++)
{
string testdna = DNAs[dnai];
for (int chari(0); chari < length; chari++) { char testchar = testdna[chari]; for (int charj(chari+1); charj < length; charj++) { if (testdna[charj] < testchar) sortScore[dnai][0]++; } }
}
qsort(sortScore, num, sizeof(int)*2, CompareFunction);
//QSort(sortScore, 0, num-1); // 自己写的快排也可以AC
for (int i(0); i < num; i++)
{
int strindex = sortScore[i][1];
cout<< DNAs[strindex] <<endl;
}
return 0;
}
相关文章推荐
- poj 1007 DNA Sorting
- poj 1007 DNA Sorting
- poj 1007 DNA Sorting
- poj 1007 DNA Sorting 解题报告
- poj 1007 DNA Sorting
- poj 1007 DNA Sorting
- POJ 1007 DNA Sorting
- POJ 1007 DNA Sorting (归并排序)
- POJ 1007 Java:DNA Sorting
- DNA Sorting - POJ 1007 排序
- poj-1007-DNA Sorting
- 【原】 POJ 1007 DNA Sorting 逆序数 解题报告
- POJ 1007 DNA Sorting
- 【POJ】1007 DNA Sorting
- POJ 1007: DNA Sorting
- POJ 1007 DNA Sorting
- poj 1007 DNA Sorting
- poj1007——DNA Sorting
- POJ 1007 DNA Sorting【求逆序数】
- POJ 1007 - DNA Sorting