C语言删除数组中重复的元素,且不能开辟空间使用新建数组

给你一个已经排好序的数组,该数组中包含n个元素,请你使用函数原地删除该数组中重复的元素,使该数组成为一个没有重复元素的数组,函数返回一个值,该值作为删除完重复元素后的数组

中含元素个数,用来在主函数中作为循环条件输出删除后数组元素。原地的要求是不能新建数组,在原数组中进行操作

在上述题目中我们得到几个有用的信息:“已排好序的数组”、“含n个元素”、“原地删除”、“不重复元素”、“返回一个值作为新数组循环输出条件”。有这几个信息我们基本可以写出这样一个主函数:

int main(){
    
    /*产生一个已经排好序的数组,无论从大到小还是从小到大,因为我们不知道
该数组有多少个元素因此这里不定义数组元素个数。*/
    int arr[] = {1,1,2,2,3,4,5,5,6};

    /*测量这个数组有多少个元素,sizeof可以用来测量该类型在内存中占用多
少个字节,我们知道一个int类型的数据在内存中占用4个字节,我们这里用该单
元占用的总字节除以该单元中一个元素在内存中占用的字节数就得到了该单元中有
多少个元素了,其实也可以直接除以int或者除以4,但是呢有的时候我们写成这样
就显得很呆板,如果是事先我们不知道的一个类型,那么我们这样写就失效啦*/
    int size = sizeof(arr)/sizeof(arr[0]);
    
    /*调用函数removeNmus(),传入实参一个是数组名arr,它是一个地址,指向
我们该数组的首元素,第二个参数是一个整型,它是我们上面所求的这个数组中元
素的个数*/
    int k = removeNums(arr,size);

    /*打印函数返回值,上面我们讲函数的返回值赋给了变量k了已经*/
    printf("%d,",k);

    /*使用for循环遍历打印这个去重后的数组,这里可以看到我们循环的条件是
i<k而不是i<size,因为我们去重后数组的元素个数减少了,而k就是我们去重后的
数组元素个数,实际上我这么说是有问题的,k并不是去重后的数组元素个数,
这个我稍后在函数那边讲*/
    for(int i=0;i<k;i++){
        printf("%d,",arr[i]);
    }
    return 0;
}

写完主函数以后我们可以来看removeNmus()函数中如何实现:

//函数定义,两个形参,一个指针型用来接收传过来的数组名,一个整型用来接收传过来的数组元素个数
int removeNums(int *nums,int numSize){

    /*定义两个整型变量,并赋初值1*/
    int head = 1,foot = 1;

    /*判断一下传过来的数组是不是空数组,是空数组的话直接返回0,函数结束*/
    if(numSize == 0){
        return 0;
    }

    /*while循环用来循环判断,只要head不等于大于numSize就说明下标为head的元素
不是该数组最后一个元素,就要继续执行循环*/
    while(head < numSize){

        /*判断后一个元素是否跟前一个元素相等,不相等就将后一个元素的值赋值给下标为foot的元素
,要注意这里foot初值为1,那么nums[foot]所指向的就是该数组中第二个元素,而此时下标为head的元素
也是数组中第二个元素,所以这一步下标为1的元素值未改变,但是后续当if条件里两者相等时,该if条件
不执行,foot不做自增,但是head却会自增,这样做就相当于过滤掉了一个与前面一个元素相等的后面
一个元素,但是在主函数中我提到的问题在这里出现了,虽然该重复元素被过滤掉了,但是该数组的
元素个数并未随之减少,而且该数组的真实长度还是为numSize,而foot的出现与返回都只是为了让
程序在打印时只打印不重复的元素,虽然程序不能如同python与Java一样达到切片的效果去真正实现删除
该程序中重复的元素并将空置的空间赋值为0,但是只要改程序满足题目所有要求即可,即使多余位上的
元素值与前面我们所需要的元素值重复也是正常的,因为无论是python和Java采用切片方法将重复值剔除
并置0还是C语言的过滤重复值,本质上都无法改变一个数组或者列表在声明时就已经确定且中途不可改变的
在内存中所占据的空间,只不过,python与Java实现了一个置0,而本程序没有,但无论是0还是其他值
都已经是多余位上的,不参与结果的计算,不过有时python与Java会明确提出实现置0的要求。*/
        if(nums[head] != nums[head-1]){

            /*此时foot的值只有当if条件成立时才会改变,因此,以foot为下标可以起到重新为该数组
中除了下标0的元素重新赋值的效果,当然即便是while循环结束该数组中最后一个值也永远无法被改变,但
这个值也永远不会被算在结果里*/
            nums[foot] = nums[head];

            /*foot用来计算新数组的元素个数,这里用新数组似乎不太合适,但是实际上我们已经是
将原数组的每个位置上的元素置换了,因此叫做新数组,同时该新数组的数组元素也只有foot个而不是
原数组的numSize个*/
            ++foot;
        }
        //让原数组下标自增用来控制while循环执行次数
        ++head;
    }
    //将foot作为返回值,此时在这里foot的含义已经不是下标,而是新数组的元素个数
    return foot;
}

第一个6是主函数打印的函数返回值foot的值也是主函数中变量k的值,后面的1,2,3,4,5,6便是去重后的数组。 

但是细心的小伙伴可以发现,当主函数中for循环的条件是i<size时,结果就会变成这样:

 这就是我在函数哪里跟大家废话了这么多的原因,就是想告诉大家,数组去重并没有改变该数组在内存中所占据的空间大小,无论是python还是Java都无法实现,因为这是程序的底层逻辑原理,一个变量或单元所占据的空间大小在他被定义或声明的那一刻起就已经确定了,在程序执行的过程中无法改变,只有当程序执行完内存释放以后该可以被改变。至于时什么原理请大家看这张图:

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值