第五十五篇:删除一个数组中多个连续或不连续重复的数字,保留一个

在直线筛选斜率的时候,碰到了去除直线的斜率相近的问题:

程序很简单,我直接拿网上的程序:

如下:

 #include "stdio.h"

//去除重复,产生新数组 
int only1(int a[],int n)
{
    int i,j,k;
    for(i=0;i<n;i++)
    {
        for(j=i+1;j<n;j++)
        {
            if(a[i]==a[j])
            {
                for(k=j;k<n-1;k++)
                {
                    a[k]=a[k+1];
                }
                n--;
     //	j--;    此处需要修
            }
        }
    }
    printf("\n\n清除重复数后的新数组:\n");
    for(i=0;i<n-1;i++)
        printf("%d  ",a[i]);
    return n-1;
}
//排序 
void sort(int a[],int n)
{
    int i,j,temp;
    for(i=0;i<n-1;i++)
    {
        for(j=i;j<n;j++)
        {
            if(a[i]<a[j])
            {
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
        }
    }
    printf("\n\n排序后的数组:\n");
    for(i=0;i<n;i++)
        printf("%d  ",a[i]); 
}
int main()
{
	int a[10]={1,2,3,7,5,6,7,7,8,16};
  //  sort(a,only1(a,10));
     only1(a,10);
}
运行结果:


为什么还是有重复呢?说明程序有漏洞,观察发现,

a[10]={1,2,3,7,5,6,7,7,8,16};
中连续的重复数字只删除了一个,说明只删除了部分,这是不是和数组的中重复数组的位置有关?怀疑:连续重复数字与间隔重复数字的删除对于此程序有漏洞的,实验一下,将数组中重复数字改为不连续的
a[10]={1,2,3,7,5,6,7,8,7,16};
运行:


果然,不连续的三个重复数字都删除后只保留了一个,

说明对程序的漏洞怀疑是正确的,那么在哪里改呢?

读原程序发现,a[i]与a[j]如果相同后,数组后面所有的数字都前移动一位,a[j]被删除,a[j+1]移动到a[j],而下一次再比较的时候从j+1开始,说明原数组中的a[j+1]被漏掉了,j+1开始循环是原数组的a[j+2],原来如此,找到问题后怎么解决呢?

每次找到相同的数字后,相同数字后面的所有数字前移动一位后,仍然从相同数字的位置开始循环,即删除第j个元素后,把j后面的元素前移动一位后,任然从j开始循环好了,修改程序就是:把我标记颜色屏蔽掉的加上,即把前面的双斜杠去掉,     

     即加上     j--;

a[10]={1,2,3,7,5,6,7,7,8,16}

运行结果:


问题解决!!!这样的编程漏洞是由于大多数人的逻辑思维定视

规范法编程可以避免:

int main() {
    int a[] = {36,25,14,63,36,25,14,36,36};
    int i,j,k,n = sizeof(a)/sizeof(a[0]);
    for(i = 0; i < n; ++i)
        printf("%d ",a[i]);
    printf("\n");
    for(i = 0; i < n; ++i) {
        for(j = i + 1; j < n - 1; ++j) {
            if(a[j] == a[i]) {
                for(k = j; k < n - 1; ++k)
                    a[k] = a[k + 1];
            }
            --n;
        }
    }
    for(i = 0; i < n; ++i)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}

这里使用的是++j,这样就避免这个问题!!!



                
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值