数据结构 线性表的唯一化算法

数据结构 线性表的唯一化算法

标签(空格分隔): 算法 数据结构


最近在看两个数据结构的网课,分别是学堂在线清华大学邓俊辉老师的和浙江大学陈越老师的,学到了很多有用的东西。比如下面这个线性表部分的算法(来自清华大学网课),对线性表进行唯一化处理的算法。

对一个线性表(课程里面用vector指代),如果想要进行它的唯一化处理,就需要每一种元素仅仅保留一个。比如说{0,1,6,4,8,1,9,4,7},进行唯一化处理之后,就是{0,1,6,4,8,9,7}。

下面有必要分两种情况进行讨论。

  1. 线性表无序。如果线性表开始就是无序的,那么显然不存在什么简化算法,只能从头开始,依次遍历,相互比较.
vector<T> a     
......            //假设a已经初始化,非空了
for (int i=0;i<a.size();i++)    
    for (int j=i+1;j<a.size();j++)  
        if (a[i]==a[j])
            remove(j);

显然,这个算法复杂度是o(n^2),效率比较低。但是,对于无序表,这个算法是我们能想到的较好的算法了。
2. 线性表有序。既然有序,那我们就能想到这样一个算法了:对每一部分相同项,都拿它们的第一个向后比较,删除所有其他的相同项。算法实现如下。

 for (int i=0;i<a.size();)  {
    T t=a[i];
    int j,i0;
    j=i;i0=i;
    while (a[++i]==t)
        remove(a[i]);
}

这个算法貌似很合理,但是不要忘了,remove操作也包含着o(n)的时间复杂度,再加上循环,可以很容易的看出,这个算法在最坏情况下,就是序列全为相同元素的情况下,每次循环需执行的操作步数为n-1,n-2,……,2,1,时间复杂度也是o(n^2),与无序序列没有差别。所以,这并不是个好算法。

再看下面这一个

int i=0;
if  (i<a.size())
{
    T t=a[i];
    int i0;
    i0=i;
    while (a[++i]==t);
    if  (i>i0)
        remove(a,i0+1,i);
    i=i0+1;
}

这个显然比上面那个要好。因为他的时间复杂度为o(n)。while循环语句起的作用仅仅是计算重复序列下标的作用,下面的if分支并没有包含在while内。但是,因为用了太多变量,这个算法还不是最好的。

再看下面这个。

for (int i-0;i<a.size();i++)    {
    int i=0,j=0;
    while (++j<a.size())  {
        if (a[i]!=a[j]) a[++i]=a[j];
    }
    i++;shrink();
}

这个算法实现了上一个算法的思想,而且没有用到逐次删除,只是在最后将所有冗余元素一次删除完了。它没有用到多次删除函数,而是一种隐式的删除,就是把j元素移到i+1处,将那个重复元素覆盖掉。目前来看,这个才是唯一化处理有序线性表的最优算法。

posted @ 2018-03-11 14:34  CF过2100就买ARCTERYX  阅读(198)  评论(0编辑  收藏  举报