目录
1.题目
顺序表ADT模板简单应用算法设计:找出两个等长升序序列的中位数
作者: 教材 时间限制: 1S 章节: DS:线性表
问题描述 :
目的:使用自行设计的顺序表ADT或STL的vector模板设计并实现顺序表应用场合的一些简单算法设计。
应用7:一个长度为L(L>=1)的升序序列S,处在第[L/2]个位置的元素称为S的中位数。例如,若序列S1 = (11,13,15,17,19),则S1的中位数为15。两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若序列S2 = (02,04,06,08,20),则S1和S2的中位数为11。假设以两个元素依值递增有序排列的线性表A和B分别表示两个升序序列(即同一表中的元素值各不相同),现要求设计在时间和空间两方面都尽可能高效的算法,找出两个长度相同的升序序列A和B的中位数。
算法提示:
方法一:可以先将两个序列合并然后再去找2n/2位置,并返回该位置的数。(时间复杂度最差)
方法二:由于两个序列都是升序,所以,直接计数n,升序排列前n个数即可。(时间复杂度居中)
方法三:减治法 (时间复杂度最好)
分别求出序列A 和B 的中位数,设为a 和b,求序列A 和B 的中位数过程如下:
1)若a=b,则a 或b 即为所求中位数,算法结束。
2)若a<b,则舍弃序列A 中较小的一半,同时舍弃序列B 中较大的一半,要求舍弃的长度相等;
3)若a>b,则舍弃序列A 中较大的一半,同时舍弃序列B 中较小的一半,要求舍弃的长度相等;
在保留的两个升序序列中,重复过程1)、2)、3),直到两个序列中只含一个元素时为止,较小者即为所求的中位数。
参考函数原型:
(1)顺序表ADT版本:
参考函数原型:template<class ElemType>
ElemType Search_Mid( SqList<ElemType> &A, SqList<ElemType> &B );
(2)vector版本:
参考函数原型:template<class ElemType>
ElemType Search_Mid( const vector<ElemType> &A, const vector<ElemType> &B );
输入说明 :
第一行:顺序表A的数据元素的数据类型标记(0:int,1:double,2:char,3:string)
第二行:有序序列A的数据元素(数据元素之间以空格分隔)
第三行:有序序列B的数据元素(数据元素之间以空格分隔)
输出说明 :
如第一行输入值为0、1、2、3之外的值,直接输出“err”
否则:
第一行:单链表A的遍历结果(数据元素之间以"->"分隔)
第二行:单链表B的遍历结果(数据元素之间以"->"分隔)
空行
第四行:序列A和B的中位数
输入范例 :
2
a b c d
d e f g输出范例 :
a,b,c,d
d,e,f,gd
2.题解
- 读题:造表+算法
- 造表:stringstream
- 算法:话都让题目给说完了...... 直接照着它说的写代码就成
3.代码实现
- 算法三,我写了两种表达方式,第一种有数据错了来着,然后换另一种表达就过了,但是我没有找到第一种表达错在哪
//第一种 template<class T> void find_mid(vector<T> &A,vector<T> &B) { print(A); print(B); cout<<endl; T mid,m_a,m_b; while(A.size()!=1 || B.size()!=1) { int len=A.size(); m_a=A[(len-1)/2]; m_b=B[(len-1)/2]; if(m_a==m_b){mid=m_a;break;} else if(m_a<m_b) { A.erase(A.begin(),A.begin()+1+(len-1)/2); B.erase(B.end()-1-(len-1)/2,B.end()); } else { B.erase(B.begin(),B.begin()+1+(len-1)/2); A.erase(A.end()-1-(len-1)/2,A.end()); } } if(A.size()==1||B.size()==1)mid=min(A[0],B[0]); cout<<mid<<endl; } //第二种 template<class T> void find_mid(vector<T> &a,vector<T> &b) { print(a); print(b); cout<<endl; T mid; int star1=0,end1=a.size()-1,m1,star2=0,end2=a.size()-1,m2; while(star1!=end1 || star2!=end2) { m1=(star1+end1)/2; m2=(star2+end2)/2; if(a[m1]==b[m2]){mid=a[m1];break;} else if(a[m1]<b[m2]) { if((star1+end1)%2) star1=m1+1,end2=m2; else star1=m1,end2=m2; } else { if((star1+end1)%2) end1=m1,star2=m2+1; else end1=m1,star2=m2; } } if(star1==end1) mid=min(a[star1],b[star2]); cout<<mid<<endl; }
- 完整代码
#include <iostream> #include <cstring> #include <vector> #include <algorithm> using namespace std; int n; string s1,s2; template<class T> void print(vector<T> &A) { if(A.size()==0) { cout<<"NULL"<<endl; return; } int i; for(i=0; i<A.size()-1; i++) cout<<A[i]<<","; cout<<A[i]<<endl; } template<class T> void find_mid(vector<T> &a,vector<T> &b) { vector<T> c; //T mid,mid_a,mid_b; print(a); print(b); cout<<endl; T mid; int star1=0,end1=a.size()-1,m1,star2=0,end2=a.size()-1,m2; while(star1!=end1 || star2!=end2) { m1=(star1+end1)/2; m2=(star2+end2)/2; if(a[m1]==b[m2]){mid=a[m1];break;} else if(a[m1]<b[m2]) { if((star1+end1)%2) star1=m1+1,end2=m2; else star1=m1,end2=m2; } else { if((star1+end1)%2) end1=m1,star2=m2+1; else end1=m1,star2=m2; } } if(star1==end1) mid=min(a[star1],b[star2]); /* while(a.size()!=1) { int len=a.size(); mid_a=a[(len-1)/2]; mid_b=b[(len-1)/2]; if(mid_a==mid_b)mid=mid_a; else if(mid_a<mid_b) { a.erase(a.begin(),a.begin()+(len-1)/2+1); b.erase(b.end()-1-(len-1)/2,b.end()); } else { b.erase(b.begin(),b.begin()+(len-1)/2); a.erase(a.end()-1-(len-1)/2,a.end()); } } if(a.size()==1)mid=min(a[0],b[0]); */ cout<<mid<<endl; } vector<int> f0(string s) { vector<int> a; int num=0; for(int i=0; i<s.size(); i++) { if(s[i]==' ') { a.push_back(num); num=0; } else { num=num*10+s[i]-'0'; } } a.push_back(num); return a; } vector<double> f1(string s) { vector<double> b; double num=0; int flag=0,t=0; for(int i=0; i<s.size(); i++) { if(s[i]==' ') { num=num/pow(10,t); b.push_back(num); t=0,num=0,flag=0; } else if(s[i]=='.') { flag=1; } else { num=num*10+s[i]-'0'; if(flag==1) t++; } } num=num/pow(10,t); b.push_back(num); return b; } vector<char> f2(string s) { vector<char> c; for(int i=0; i<s.size(); i++) { if(s[i]!=' ') c.push_back(s[i]); } return c; } vector<string> f3(string s) { vector<string> d; string str; str.clear(); for(int i=0; i<s.size(); i++) { if(s[i]==' ') { d.push_back(str); str.clear(); } else str+=s[i]; } if(str!="") d.push_back(str); return d; } int main() { cin>>n; getchar(); getline(cin,s1); getline(cin,s2); if(n==0) { vector<int> A1,A2; A1=f0(s1); A2=f0(s2); find_mid(A1,A2); } else if(n==1) { vector<double> B1,B2; B1=f1(s1); B2=f1(s2); find_mid(B1,B2); } else if(n==2) { vector<char> C1,C2; C1=f2(s1); C2=f2(s2); find_mid(C1,C2); } else if(n==3) { vector<string> D1,D2; D1=f3(s1); D2=f3(s2); find_mid(D1,D2); } else cout<<"err"<<endl; return 0; }
#include <iostream> #include <vector> #include <sstream> #include <cstring> #include <algorithm> using namespace std; int n; string s1,s2; template<class T> void print(vector<T> &A) { typename std::vector<T>::iterator it=A.begin(); for(;it!=A.end()-1;it++) cout<<*it<<","; cout<<*it<<endl; } template<class T> void creat(stringstream &input,vector<T> &A) { T str; while(input>>str)A.push_back(str); } template<class T> void find_mid(vector<T> &A,vector<T> &B) { print(A); print(B); cout<<endl; T mid,m_a,m_b; while(A.size()!=1 || B.size()!=1) { int len=A.size(); m_a=A[(len-1)/2]; m_b=B[(len-1)/2]; if(m_a==m_b){mid=m_a;break;} else if(m_a<m_b) { A.erase(A.begin(),A.begin()+1+(len-1)/2); B.erase(B.end()-1-(len-1)/2,B.end()); } else { B.erase(B.begin(),B.begin()+1+(len-1)/2); A.erase(A.end()-1-(len-1)/2,A.end()); } } if(A.size()==1||B.size()==1)mid=min(A[0],B[0]); cout<<mid<<endl; } int main() { cin>>n; getchar(); getline(cin,s1); getline(cin,s2); stringstream in1(s1); stringstream in2(s2); if(n==0) { vector<int> a1,a2; creat(in1,a1); creat(in2,a2); find_mid(a1,a2); } else if(n==1) { vector<double> b1,b2; creat(in1,b1); creat(in2,b2); find_mid(b1,b2); } else if(n==2) { vector<char> c1,c2; creat(in1,c1); creat(in2,c2); find_mid(c1,c2); } else if(n==3) { vector<string> d1,d2; creat(in1,d1); creat(in2,d2); find_mid(d1,d2); } else cout<<"err"<<endl; return 0; }