用代码实现对数组重复元素的去重-面试思考题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用代码实现对数组重复元素的去重-面试思考题相关的知识,希望对你有一定的参考价值。

这道题主要是考察array_unqiue 的底层实现

php中array_unique源码为:

 PHP_FUNCTION(array_unique)
 4 {
 5     // 定义变量
 6     zval *array, *tmp;
 7     Bucket *p;
 8     struct bucketindex {
 9         Bucket *b;
10         unsigned int i;
11     };
12     struct bucketindex *arTmp, *cmpdata, *lastkept;
13     unsigned int i;
14     long sort_type = PHP_SORT_STRING;
15 
16     // 解析参数
17     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &sort_type) == FAILURE) {
18         return;
19     }
20 
21     // 设置比较函数
22     php_set_compare_func(sort_type TSRMLS_CC);
23 
24     // 初始化返回数组
25     array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
26     // 将值拷贝到新数组
27     zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval*));
28 
29     if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {    /* 什么都不做 */
30         return;
31     }
32 
33     /* 根据target_hash buckets的指针创建数组并排序 */
34     arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->persistent);
35     if (!arTmp) {
36         zval_dtor(return_value);
37         RETURN_FALSE;
38     }
39     for (i = 0, p = Z_ARRVAL_P(array)->pListHead; p; i++, p = p->pListNext) {
40         arTmp[i].b = p;
41         arTmp[i].i = i;
42     }
43     arTmp[i].b = NULL;
44     // 排序
45     zend_qsort((void *) arTmp, i, sizeof(struct bucketindex), php_array_data_compare TSRMLS_CC);
46 
47     /* 遍历排序好的数组,然后删除重复的元素 */
48     lastkept = arTmp;
49     for (cmpdata = arTmp + 1; cmpdata->b; cmpdata++) {
50         if (php_array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
51             lastkept = cmpdata;
52         } else {
53             if (lastkept->i > cmpdata->i) {
54                 p = lastkept->b;
55                 lastkept = cmpdata;
56             } else {
57                 p = cmpdata->b;
58             }
59             if (p->nKeyLength == 0) {
60                 zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
61             } else {
62                 if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
63                     zend_delete_global_variable(p->arKey, p->nKeyLength - 1 TSRMLS_CC);
64                 } else {
65                     zend_hash_quick_del(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h);
66                 }
67             }
68         }
69     }
70     pefree(arTmp, Z_ARRVAL_P(array)->persistent);
71 }

#########################################################################################################################################################

  还想深挖的给大家推荐几篇好文章:

     http://blog.csdn.net/lz610756247/article/details/51512918

  php源码注释:https://github.com/hoohack/read-php-src

#####################################################################################################

自己用php实现该函数的底层。

思路:

1.还是先对数组进行排序。

 

//第一步:先对数组排序,采用冒泡排序

function bubble($arr)

{

  $len = count($arr);    //计算数组元素的个数

  for($i =1 ; $i< $len ;$i++)   // 对比次数

  {

    for($j = 0;$j<$len-$j;$j++)  //循环次数

    {

      if($arr[$i] > $arr[$j])

      {

        $temp  = $arr[$i] ;

        $arr[$i] = $arr[$j];

        $arr[$j] = $temp; 

      }

    }

  }

  return $arr;

}

//主函数function  dd($arr)

{

  $data = bubble($arr);

  for($i = 0; $i < count($data);$i++)

  {

      if($data[$i] == $data[$i+1])

      {

        unset($data[$i+1]);

      }  

  }

  return $arr;

}

$arr = [2,3,42,1,23,2,4,55,73,5];

dd($arr);

######

补充:运行上述代码会包一个notice的错误,用error_reporting(E_ALL||E_NOTICE)屏蔽错误就可以了

主要原因 是$data数组是索引数组,unset以后,键会出现空缺部分,所以报错,其实不算报错,算是php的一个“提醒”。

 

以上是关于用代码实现对数组重复元素的去重-面试思考题的主要内容,如果未能解决你的问题,请参考以下文章

iOS数组的去重,判空,删除元素,删除重复元素 等

数组的去重,以及随机一个验证码

JS中数组对象去重

数组的去重方法

经典面试题

iOS 数组的去重(普通的无序的去重和排序好的去重)