| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 609 人关注过本帖
标题:浅议“删除向量(数组)中多余元素”的基本操作及其优化
只看楼主 加入收藏
巧若拙
Rank: 4
来 自:宁波余姚
等 级:业余侠客
威 望:1
帖 子:159
专家分:273
注 册:2014-8-24
结帖率:46.15%
收藏
已结贴  问题点数:20 回复次数:2 
浅议“删除向量(数组)中多余元素”的基本操作及其优化
浅议“删除向量(数组)中多余元素”的基本操作及其优化
巧若拙

向量(数组)是一种紧凑的数据结构,向量的各种基本操作代码简单,容易理解,但由于在执行“插入”和“删除”操作时,需要移动大量元素,尤其在删除多个元素时,可能会产生大量重复移动,效率低下。
本文以“删除一个有序向量中多余的值相同的元素”为例,分析“删除向量中多余元素”的基本操作及其优化方法。
一,基本思想:
该算法的基本思想是:由于向量中的元素按元素值非递减有序排列,值相同的元素必为相邻的元素,因此依次比较相邻的两个元素,若值相等,则删除其中一个,否则继续向后查找,最后返回向量的新的长度。代码如下:
int DelSameElem_1(int vec[], int n)
{
    int i, j;
   
    i = 0;
    while (i < n-1)
    {
        if (vec[i] != vec[i+1])
        {
            i++;
        }
        else //每检测到一个相同元素,即删除多余的一个
        {
            for (j=i; j<n-1; j++)
            {
                vec[j] = vec[j+1];
            }
            n--;
        }
    }
   
    return n;
}

二,第一步优化
    在基础算法中,每检测到一个多余相同元素,即进行删除操作,导致大量重复移动,效率低下。如果能够将多余元素整块删除的话,可以减少重复移动,提高效率。
我们通过一个实例来分析整块删除方法:
初始向量:vec[8] = {1,2,2,2,2,2,3,4}。
向量中值为“2”的元素共有5个,其中有4个是多余的,我们可以将vec[6..7]一次性前移,覆盖掉需要删除的多余元素,并将向量长度减4,即得到新的向量:
vec[4] = {1,2,3,4}。
改进后代码如下:
int DelSameElem_2(int vec[], int n) //改进版1:整块删除多余相同元素
{
    int i, j, k;
   
    for (k=0,i=1; i<n; i++)
    {
        if (vec[i] == vec[i-1])
        {
            k++; //累计多余的相同元素个数
        }
        else if (k > 0) //整块删除多余的元素
        {
            for (j=i; j<n; j++)
            {
                vec[j-k] = vec[j];
            }
            i -= k;
            n -= k;
            k = 0;
        }
    }
   
    return n - k; //尾部的多余元素直接去掉
}

三,第二步优化
    在改进版1中,我们可以一次性删除一整段多余元素,减少了一些重复移动,但是,如果向量中存在多段多余元素时,后面的元素难免被多次重复移动,效率依然不高。
我们通过一个实例来分析:
初始向量:vec[10] = {2,2,2,2,3,3,3,4,4,4}。
第一次删除:将vec[4..9]一次性前移,覆盖掉值为“2”的多余元素,得到新的向量:vec[7] = {2,3,3,3,4,4,4}。
第二次删除:将vec[4..6]一次性前移,覆盖掉值为“3”的多余元素,得到新的向量:vec[5] = {2,3, 4,4,4}。
最后将尾部的多余元素直接去掉,得到新的向量:vec[3] = {2,3, 4}。
我们发现,在上面的实例中,值为“3”的元素移动了一次,值为“4”的元素移动了2次——还是有重复移动。能否让每个元素都只移动一次就实现删除功能呢?
可以。代码如下:
int DelSameElem_3(int vec[], int n) //改进版2:高效覆盖多余相同元素,达到删除目的
{
    int i, k;
   
    for (k=0,i=1; i<n; i++)
    {
        if (vec[i] == vec[i-1])
        {
            k++;
        }
        else
        {
            vec[i-k] = vec[i];
        }
    }
   
    return n-k;
}


四,更一般化的删除向量元素的方法
    前面的例子我们分析了“删除一个有序向量中多余的值相同的元素”,实际需要我们删除满足某种条件的若干元素,我们可以设计一个标记函数,把满足删除条件的元素改为标记值,然后进行高效删除。代码如下:
void Mark(int vec[], int n, int tag)// 满足删除条件的元素改为标记值
{
    int i;
   
    for (i=1; i<n; i++)
    {
        if (vec[i-1] == vec[i])
        {
            vec[i-1] = tag;
        }
    }
}

int DelElem(int vec[], int n)
{
    int i, k;
    int tag = vec[0] - 1; //将需要被删除的元素赋值为tag
   
    Mark(vec, n, tag);
   
    for (k=0,i=0; i<n; i++)
    {
        if (vec[i] == tag)
        {
            k++;
        }
        else
        {
            vec[i-k] = vec[i];
        }
    }
   
    return n-k;
}
搜索更多相关主题的帖子: 元素 
2014-09-09 09:26
yuccn
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:何方
等 级:版主
威 望:167
帖 子:6814
专家分:42393
注 册:2010-12-16
收藏
得分:20 
呵呵

我行我乐
公众号:逻辑客栈
我的博客:
https://blog.yuccn. net
2014-09-12 12:37
soulmate1023
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:256
专家分:831
注 册:2014-9-23
收藏
得分:0 
学习了
2014-09-24 23:24
快速回复:浅议“删除向量(数组)中多余元素”的基本操作及其优化
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015145 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved