用代码实现对数组重复元素的去重-面试思考题
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的一个“提醒”。
以上是关于用代码实现对数组重复元素的去重-面试思考题的主要内容,如果未能解决你的问题,请参考以下文章