日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Standard C Library - 思维火花 - 博客频道 - CSDN.NET

發布時間:2025/3/15 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Standard C Library - 思维火花 - 博客频道 - CSDN.NET 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Standard C Library - 思維火花 - 博客頻道 - CSDN.NET

? DIY 了一套 ACQUIRE |
返回首頁
| 骨骼動畫的插值與融合 ?

動態數組的 C 實現

上次談到了一個常用的 ADT ,sequence 的 C 實現。通常,我們不會直接使用 sequence ,而是用它來實現滿足最終需要的數據結構。比如消息隊列,比如指令堆棧,等等。一個實現的優秀的 seq 的好處在于,即使你只用到其中一部分功能,也不會因為那些沒用的部分損失太多的(時間和空間上的)性能。

今天我想談另一個更為實用的 ADT ,動態數組。這個在傳世神作《C 語言接口與實現》中也提到過,我不是想說其寫的不對,或是講述的不周全,實現的不漂亮。只是以我的觀點來展開相關的問題。

為什么要有數組?C 語言內置了數組、在 C99 中更是允許在堆棧上聲明非固定長度的數組。C++ 里以 STL 的形式提供了 vector 模塊供程序員使用。

我們面臨的問題,不是語言和庫為我們提供了多少可能。而是我們無法確定,我們到底至少需要什么?

通常,數組讓我們可以隨機(以 O(1) 的時間復雜度)訪問其內的數據。但是,隨機訪問不是目的,而是手段。我們究竟需要一個數組解決怎樣的問題?面對怎樣的問題,需要處理的數據需要以數組方式組織?我這幾年始終不敢說自己得到了確切的答案。往往,我們只是直覺上感覺,用一個 vector (使用 C++ )非常方便,所以就用了。當我在用 C 的時候,我總是隨手寫上一個 realloc ,來擴展我的數據塊。最近一段時間,我覺得有必要歸納一下需求,設計一個通用模塊來統一解決問題了。

思考的結果就是:當我們周期性的聚合一堆數據時,我們需要一個數組,且這個數組的長度是不確定的,應該可以動態增長。

數組最重要的特性是可以最高效的遍歷,即依次處理數組內部的元素。在 C 語言的層面考慮這個問題時,就應該更細致考慮實現的差別引起的性能差異。比如鏈表的遍歷同樣是 O(N) ,但是時間和空間的開銷都是大于連續內存空間的數組的。

我們需要快速的清空數組,方便下一個周期聚合新的數據。

我們需要對數據排序,使得按我們的需要的次序去依次處理(遍歷)數組中的元素。

有時候,我們需要相對快速的查找。一旦數據是有序的,二分查找可以讓時間復雜度減少到 O(log n) 。

其它,我們不再需要。

注:我們往往混淆了另一個需求。很多時候,我們把數組當成了一個高性能卻有局限性的 key-value 字典。這個 key 就是數組內數據的數字索引。對于用一個 key (可能是數,也可能不是)快速索引到值的需求,應該放到另一個地方去考慮。

?


?

最終,我為 array 這個 ADT 提供了如下的方法:

struct array * array_create(int atom_size); void array_release(struct array *); void array_clear(struct array *); void array_push(struct array *, void *atom); void array_iterator(struct array *, seqi iter); void array_sort(struct array *, int (*compar)(void *,void *));

這里,暫時沒有提供 binarysearch 方法,因為暫時我還沒有用到。我還不確定是不是真的有意義,以及最佳的接口定義應該是怎樣。

在實現時,我開辟了一整塊連續內存保存數據。當使用者 push 一個元素時,采用值復制的方式,復制到 array 內部。然后用 seq 來管理對內部元素的引用(指針)。

當數據區不夠大時,采用 realloc 擴展數據區內存。一旦內存地址發生變化,則修改對應的 seq 里的指針。把索引和數據分開存放,可以提高排序的效率(數據交換量比較小)。

sort 函數提供了一個類似 qsort 接口的比較函數。但是,由于和 qsort 的定義有所不同,所以不能直接去調用 qsort 。在 glibc 中,有另一個 qsort_r 可以滿足需求。不過我考慮到性能,自己重新實現了一個快速排序。反正,也沒幾行代碼。

?


?

這里,由于數據在內存中的位置并不固定。從 seqi 中拿到的指針是不可以被傳遞保存到別的數據結構體中的。包括 seqi 這個迭代子,根據上篇關于 sequence 實現的描述,也不允許長期保留。你可以認為,這是這個 ADT 的局限性。不過我個人認為,我們每設計一個東西,只應該解決有限的,定義好的需求。而不應該包羅萬象。

只做一件事,并把它做好。

總結

以上是生活随笔為你收集整理的Standard C Library - 思维火花 - 博客频道 - CSDN.NET的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。