C++ 编写按字典顺序添加新元素的链接函数的更短/更有效的方法
我试图练习编程原理和实践文本,花了一段时间进行调试,直到最终为函数编写了一个工作代码。演习是这样开始的: 我为链接创建了模板类:C++ 编写按字典顺序添加新元素的链接函数的更短/更有效的方法,c++,c++11,linked-list,doubly-linked-list,C++,C++11,Linked List,Doubly Linked List,我试图练习编程原理和实践文本,花了一段时间进行调试,直到最终为函数编写了一个工作代码。演习是这样开始的: 我为链接创建了模板类: template<typename T> struct Link { T val; Link* prev; Link* succ; Link(const T& value, Link* p = nullptr, Link* s = nullptr) :val{value},prev {p}, suc
template<typename T>
struct Link
{
T val;
Link* prev;
Link* succ;
Link(const T& value, Link* p = nullptr, Link* s = nullptr)
:val{value},prev {p}, succ{ s } {}
Link* add_ordered_(Link*);
};
我使用print_link函数打印出元素,以便于调试:
template<typename T>
void print_link(Link<T>* x)
{
while (x)
{
cout << x->val << endl;
x = x->prev;
}
}
我编写的add\u ordered\u
函数似乎太长、难看且效率低下。如果有人向我展示一种更有效的书写方法,我会很高兴的。拆分您的方法:
std::pair<Link*, Link*> find_neighbor(const Link& link) {
// assert(prev == nullptr);
Link* left = nullptr; // == prev
Link* right = this;
while (right && right->val < link.val) {
left = right;
right = right->succ;
}
return {left, right};
}
void insert_between(Link* left, Link* right)
{
prev = left;
succ = right;
if (left) {
left->succ = this;
}
if (right) {
right->prev = this;
}
}
Link* add_ordered_(Link* link)
{
// assert(prev == nullptr); // Assume we call it only with first element
if (link == nullptr) {
return this;
}
auto p = find_neighbor(*link);
link->insert_between(p.first, p.second);
if (prev) {
return prev; // == link
}
return this;
}
std::配对查找邻居(常量链接和链接){
//断言(prev==nullptr);
Link*left=nullptr;//==prev
链接*右=此;
while(right&&right->val成功;
}
返回{左,右};
}
在(链接*左,链接*右)之间插入空格
{
prev=左;
成功=正确;
如果(左){
左->成功=此;
}
如果(右){
右->上一个=这个;
}
}
链接*添加\订购\链接*链接
{
//assert(prev==nullptr);//假设我们只使用第一个元素调用它
if(link==nullptr){
归还这个;
}
自动p=查找邻居(*链接);
链接->插入(第一页,第二页);
如果(上一个){
返回上一个;//==链接
}
归还这个;
}
拆分您的方法:
std::pair<Link*, Link*> find_neighbor(const Link& link) {
// assert(prev == nullptr);
Link* left = nullptr; // == prev
Link* right = this;
while (right && right->val < link.val) {
left = right;
right = right->succ;
}
return {left, right};
}
void insert_between(Link* left, Link* right)
{
prev = left;
succ = right;
if (left) {
left->succ = this;
}
if (right) {
right->prev = this;
}
}
Link* add_ordered_(Link* link)
{
// assert(prev == nullptr); // Assume we call it only with first element
if (link == nullptr) {
return this;
}
auto p = find_neighbor(*link);
link->insert_between(p.first, p.second);
if (prev) {
return prev; // == link
}
return this;
}
std::配对查找邻居(常量链接和链接){
//断言(prev==nullptr);
Link*left=nullptr;//==prev
链接*右=此;
while(right&&right->val成功;
}
返回{左,右};
}
在(链接*左,链接*右)之间插入空格
{
prev=左;
成功=正确;
如果(左){
左->成功=此;
}
如果(右){
右->上一个=这个;
}
}
链接*添加\订购\链接*链接
{
//assert(prev==nullptr);//假设我们只使用第一个元素调用它
if(link==nullptr){
归还这个;
}
自动p=查找邻居(*链接);
链接->插入(第一页,第二页);
如果(上一个){
返回上一个;//==链接
}
归还这个;
}
把事情分解成简单的小部分通常是个好主意 让我们向类中添加另外两个函数,
add\u在
之后和add\u在
之前
template<typename T>
Link<T>* Link<T>::add_after(Link<T>*n)
{
if (succ) {
n->succ = succ;
}
succ = n;
n->prev = this;
}
template<typename T>
Link<T>* Link<T>::add_before(Link<T>*n)
{
if (prev) {
n->prev = prev;
}
prev = n;
n->succ = this;
}
把事情分解成简单的小部分通常是个好主意 让我们向类中添加另外两个函数,
add\u在
之后和add\u在
之前
template<typename T>
Link<T>* Link<T>::add_after(Link<T>*n)
{
if (succ) {
n->succ = succ;
}
succ = n;
n->prev = this;
}
template<typename T>
Link<T>* Link<T>::add_before(Link<T>*n)
{
if (prev) {
n->prev = prev;
}
prev = n;
n->succ = this;
}
if(this==nullptr)
。无法发生(UB情况除外)。将方法分为两部分:查找插入位置。在位置插入。if(this==nullptr)
。无法发生(UB情况除外)。将方法分为两部分:查找插入位置。插入位置。谢谢。真的很有帮助,谢谢。真的很有帮助。
template<typename T>
Link<T>* Link<T>::add_after(Link<T>*n)
{
if (succ) {
n->succ = succ;
}
succ = n;
n->prev = this;
}
template<typename T>
Link<T>* Link<T>::add_before(Link<T>*n)
{
if (prev) {
n->prev = prev;
}
prev = n;
n->succ = this;
}
template<typename T >
Link<T>* Link<T>::add_ordered_(Link<T>*n)
{
Link* insert = this;
if (n->val > insert->val) {
insert->add_before(n);
return n;
}
while (n->val < insert->val && insert->succ)
insert = insert->succ;
if (n->val > insert->val)
insert->add_before(n);
else
insert->add_after(n);
return this;
}