博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TAOCP3中一道关于对序列重排的题目的实现
阅读量:7137 次
发布时间:2019-06-28

本文共 3760 字,大约阅读时间需要 12 分钟。

原题参照TAOCP3习题Section 5, 24题

题目大约是,有一个有序的单向链表,每一个元素形如<a, b>,a和b分别是一个元素(在我的解法中用字符串表示)。输入是一个文件,文件中有N-1个形如上述的元祖(N为链表中实际元素的个数),顺序随机。要求输出元祖所指示的原先的序列。比如,输入是,<k4, k5> <k1, k2> <k3, k4> <k2, k3>,链表重建为<k1, k2> <k2, k3> <k3, k4> <k4, k5>,输出为k1 k2 k3 k4 k5。

代码:

/************************* copyright @watofall no guarantee for bugfree!**************************/#include 
#include
#include "string.h"#include
#include
using namespace std;#define MAX_CHAR 100#define MAX_PAIR 100typedef struct Pair{ char *val; char *next;}Pair;typedef struct NumVal{ int sequence; char *val;}NumVal;bool comp1(Pair a, Pair b){ if(strcmp(a.val, b.val) < 0) return true; else return false;}bool comp2(Pair a, Pair b){ if(strcmp(a.next, b.next) < 0) return true; else return false;}bool comp3(NumVal a, NumVal b){ if(strcmp(a.val, b.val) < 0) return true; else return false;}bool comp4(NumVal a, NumVal b){ return a.sequence < b.sequence;}int main() { ifstream fin ("sort_pair2.in"); int i, j, k, count, t; char buf1[MAX_CHAR], buf2[MAX_CHAR]; vector
pairs, pairs_b, pairs_; vector
num_vals, num_vals_; for(i = 0; fin.good(); i ++) { fin >> buf1 >> buf2; Pair new_pair; new_pair.val = new char[strlen(buf1)]; new_pair.next = new char[strlen(buf2)]; strcpy(new_pair.val, buf1); strcpy(new_pair.next, buf2); pairs.push_back(new_pair); } count = i + 1; pairs_b = pairs; sort(pairs.begin(), pairs.end(), comp1); sort(pairs_b.begin(),pairs_b.end(), comp2); // find the last element for(i = 0, j = 0; j < count - 1;) { if(i >= count - 1) // find miss match { NumVal new_num_val; new_num_val.sequence = count; new_num_val.val = pairs_b[j].next; num_vals.push_back(new_num_val); j ++; } else if(strcmp(pairs_b[j].next, pairs[i].val) == 0) // find match { i ++; j ++; } else if(strcmp(pairs_b[j].next, pairs[i].val) > 0) // go on match to the next element { i ++; } else // find miss match { NumVal new_num_val; new_num_val.sequence = count; new_num_val.val = pairs_b[j].next; num_vals.push_back(new_num_val); j ++; } } // match and add for(t = 1; t <= count; t *= 2) { pairs_b = pairs; sort(pairs.begin(), pairs.end(), comp1); sort(pairs_b.begin(), pairs_b.end(), comp2); sort(num_vals.begin(), num_vals.end(), comp3); pairs_.clear(); num_vals_ = num_vals; for(i = 0, j = 0, k = 0; i < count - t;) { if(j < count - t && strcmp(pairs_b[i].next, pairs[j].val) == 0) // pairs_b match pairs { Pair new_pair; new_pair.val = pairs_b[i].val; new_pair.next = pairs[j].next; pairs_.push_back(new_pair); i ++; j ++; continue; } if(k < num_vals.size() && strcmp(pairs_b[i].next, num_vals[k].val) == 0) // pairs_b match num_vals { NumVal new_num_val; new_num_val.sequence = num_vals[k].sequence - t; new_num_val.val = pairs_b[i].val; num_vals_.push_back(new_num_val); i ++; k ++; continue; } if(j < count - t && strcmp(pairs_b[i].next, pairs[j].val) > 0) // go on search pairs { j ++; continue; } if(k < num_vals.size() && strcmp(pairs_b[i].next, num_vals[k].val) > 0) { k ++; continue; } } pairs = pairs_; num_vals = num_vals_; } sort(num_vals.begin(), num_vals.end(), comp4); cout << "results :" << endl; for(i = 0; i < num_vals.size(); i ++) { cout << num_vals[i].val << " "; }}

sample input :

e f

f j
h i
i u
b o
w x
x y
y z
z c
c d
u v
v w
s a
q r
r s
o p
p t
t g
g h
a b
d e
j k
k l
l m
m n

results :

q r s a b o p t g h i u v w x y z c d e f j k l m n

算法的主要思路是利用排序能够快速找出两个集合中相同元素的性质,维护三个数组F H G,F为剩下的元祖,H和F相同,F按元组的第二个元素升序(字典序,与输出的序列无关,方便查重)排列,H按元组的第一个元素升序排列,G是已经知道序列的最终序列中的末尾元素,以元素字典序的升序排列。H中元组的跨度t不断增加(即对<a, b>,t为在结果序列中a经过几次访问到达b),且不断乘2,因此外部循环为lg(n)次。而内部循环由于有排序,复杂度为O(nlg(n)),故总体时间复杂度为O(nlg2(n))。

转载地址:http://gmcrl.baihongyu.com/

你可能感兴趣的文章
算法学习之路|逆元取模(一)
查看>>
通过Lotus Notes7.0.1客户端收发MDaemon邮件
查看>>
学习分区表应该了解的参数
查看>>
Spring Data Elasticsearch 与 Elasticsearch 的关系
查看>>
puppet完全攻略(二)让puppet代码支持vim高亮显示
查看>>
解决了wanda小鱼的中文乱码问题
查看>>
php 之常用技巧!
查看>>
Python在HiveQL中的运用
查看>>
windows mobile开发循序渐进(1)关于平台和工具
查看>>
windows mobile开发循序渐进(3)移动应用程序的数据存储之本地数据存储第一篇
查看>>
Win7 64位环境下JDK和Eclipse的选择与安装
查看>>
CentOS 5.2下Memcache的安装与配置
查看>>
虚拟机安装以及PCL的配置(2)
查看>>
如何查看Linux的相关配置信息
查看>>
WCF客户端动态设置WCF服务器主机的地址的方法参考,可以连接多个相同WCF主机的方法...
查看>>
WIN8外包团队【经验分享】——升级WIN8.1后VS2012报错解决方法
查看>>
Swift 3.0封装 URLSession 的GET/SET方法代替 Alamofire
查看>>
HMP调度器
查看>>
Solaris 网络安装(X86)
查看>>
Security Considerations for AppLocker
查看>>