从数组中删除元素的算法

以下代码中,s是待删除元素的数组.v_deleted以s德索引为索引,指出s中索引对应的元素是否需要删除.即若v_deletedi=true,则si需要删除,否则应当保留

算法的目标是删除s中所有被v_deleted标记的元素,同时返回一个数组,数组索引为i的元素指出被删除元素后的s索引为i的元素在删除前的s中的索引.

该算法有两种不同的实现,分别由delete_in_list和delete_in_list2两个函数给出

两种算法的最明显的不同之处在于,delete_in_list先将s拷贝到链表assist_space,在assist_space上删除,再把assist_space拷贝回s,而delete_in_list2直接在s上执行删除,这样当s非常大或要删除的元素很多且T的析构开销非常大时, delete_in_list的效率会比delete_in_list2更高

C++代码:

cpp 复制代码
#include <iostream>
#include <vector>
#include <list>

using std::vector;
using std::list;

template<typename T>
vector<size_t> delete_in_list(vector<T>& s, const vector<int>& v_deleted)  //从left中删除被标记被删除的顶点,返回旧顶点索引和新索引映射关系的数组
{
    vector<size_t> assist_v(s.size());
    for (size_t k = 0; k < assist_v.size(); ++k)
    {
        assist_v[k] = k;
    }
    list<T> assist_space;
    assist_space.insert(assist_space.end(), s.begin(), s.end());
    bool find_new_delete_start = false;
    size_t new_delete_start_index = 0;
    size_t new_delete_start_for_assist = 0;
    typename list<T>::iterator it = assist_space.begin();
    size_t k = 0;
    for (; k < s.size(); ++k)
    {
        if (v_deleted[k] == 1)
        {
            if (find_new_delete_start == false)
            {
                find_new_delete_start = true;
                new_delete_start_index = k;
            }
        }
        else
        {
            if (find_new_delete_start)
            {
                auto d_r = assist_v.erase(assist_v.begin() + new_delete_start_for_assist, assist_v.begin() + (new_delete_start_for_assist + k - new_delete_start_index));
                auto run_it = it;
                for (size_t m = 0; m < k - new_delete_start_index; ++m)
                {
                    ++run_it;
                }
                it = assist_space.erase(it, run_it);

                find_new_delete_start = false;
                new_delete_start_for_assist = d_r - assist_v.begin();
            }
            ++new_delete_start_for_assist;
            ++it;
        }
    }

    if (find_new_delete_start)
    {
        assist_v.erase(assist_v.begin() + new_delete_start_for_assist, assist_v.end());
        assist_space.erase(it, assist_space.end());
    }

    //size_t v_num_before_delete = left.size();
    s.clear();
    s.insert(s.end(), assist_space.begin(), assist_space.end());
    /*vector<size_t> index_after_delete_to_original(v_num_before_delete);
    for (size_t m = 0; m < assist_v.size(); ++m)
    {
        index_after_delete_to_original[assist_v[m]] = m;
    }*/
    return assist_v;
}

template<typename T>
vector<size_t> delete_in_list2(vector<T>& s, const vector<int>& v_deleted)
{
    typename vector<T>::iterator it = s.begin();
    vector<size_t> assist_v(s.size());

    for (size_t i = 0; i < assist_v.size(); ++i)
    {
        assist_v[i] = i;
    }

    vector<size_t>::iterator run_a = assist_v.begin();
    typename vector<T>::iterator delete_start;
    vector<size_t>::iterator delete_start_a;
    while (true)
    {
        while (it != s.end() && v_deleted[*run_a] == 0)
        {
            ++it;
            ++run_a;
        }

        if (it == s.end())
        {
            break;
        }

        delete_start = it;
        delete_start_a = run_a;
        do
        {
            ++it;
            ++run_a;
        } while (it != s.end() && v_deleted[*run_a] == 1);

        it = s.erase(delete_start, it);
        run_a = assist_v.erase(delete_start_a, run_a);

        if (it == s.end())
        {
            break;
        }
    }
    return assist_v;
}  //当s非常大或要删除的元素很多且T的析构开销非常大时, delete_in_list的效率会比delete_in_list2更高

template<typename T>
void subset(vector<int>& v_deleted, size_t index, const vector<T>& s)
{
    if (index == s.size())
    {
        vector<T> t1 = s;
        vector<size_t> r1 = delete_in_list2(t1, v_deleted);
        vector<T> t2 = s;
        vector<size_t> r2 = delete_in_list(t2, v_deleted);
        if (t1 != t2 || r1 != r2)
        {
            std::cout << "error" << std::endl;
            exit(-1);
        }
        return;
    }

    v_deleted[index] = 0;
    subset(v_deleted, index + 1, s);
    v_deleted[index] = 1;
    subset(v_deleted, index + 1, s);
}
int main()
{
    const int N = 5;
    vector<int> s(N);
    for (int i = 0; i < N; ++i)
    {
        s[i] = i;
    }
    vector<int> v_deleted(N);
    subset(v_deleted, 0, s);
    return 0;
}
相关推荐
云泽80841 分钟前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
wlsh151 小时前
Go 迭代器
算法
Tri_Function1 小时前
简单图论大学习
c++
语戚1 小时前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
lqqjuly2 小时前
C++ 完整知识体系—从基础语法到现代 C++23 的系统性总结
c++·c++23
CS创新实验室2 小时前
从顺序表到动态数组:数据结构的永恒基石与现代语言的优雅封装
数据结构·算法
王老师青少年编程2 小时前
信奥赛C++提高组csp-s之FHQ Treap
c++·csp·平衡树·信奥赛·csp-s·提高组·fhq treap
Black蜡笔小新3 小时前
自动化AI算法训练服务器DLTM训推一体化平台助力农业生产管理实现安全智能化
人工智能·算法·自动化
8Qi84 小时前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·
QiLinkOS4 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源