「數據結構」和「數據類型」兩個概念的本質是什麼,區別與聯繫是什麼?

嚴蔚敏編著的《數據結構》教材對數據結構的定義:

相互之間存在一種或多種特定關係的數據元素的集合。

有人說,數據結構就是用來存放有特定關係的數據的容器。

數據類型是數據的一種分類,是按照數據結構來分類的。數據類型的出現是為了把數據分成所需內存大小不同的數據。

還是不太明白,貌似數據結構中包含了數據類型,而數據類型又建立在數據結構之上?
那麼數組到底是一種數據結構還是一種數據類型呢?是不是除了線性表、隊列、堆棧、樹......這些,int char double 也可以看成一種簡單的只有一個數據元素的數據結構呢?


數據類型(data type) = 介面(interface) + 數據的表示(data representation)
數據表示有多種, 數據結構(data structural representation)的表示形式是其中一種.
Essential of Programming Languages, 3rd Edition (豆瓣) 第二章講的應該就是這個了.

另外酷殼上的這篇 類型的本質和函數式實現 也相關.


感謝 Leo Ding 和 毛自力 ,兩位說的對我很有啟發

我補充一下我的想法,還是延續 原子 和 分子 的比喻。
int char float double 這些是 數據類型 ,類比作原子,他們間的不同就是元素種類的不同,只涉及自身的不同,比如兩種原子內的質子中子數不同,是一種內在屬性。
鏈表 隊列 堆棧 樹 這些是數據結構,類比作分子,他們間描述的是數據間的關係,就如同分子描述了原子的組合方式,

/*
感謝 葉子童 的提醒,補充一下,如果覺得接下來的比喻不好理解,請依然按照 原子 和 分子 理解就行了
實際上,數據類型是一種 屬性,數據結構是一種 關係,都很抽象,嚴格說起來,應該把數據類型比作元素種類,數據結構類比作化學式/分子式。但是這樣沒有起到比喻說理的效果,依然很抽象,所以依然選擇 原子 和 分子 來說明(一般人想到原子應該都會覺得就像一個一個小球吧,這樣就更易理解)。
*/

再說說只含有一個數據的鏈表/隊列/堆棧/樹,依據你給的定義:「相互之間存在一中或多種特定關係的數據元素的集合」,只含有一個數據甚至不含有數據也能算作一個「集合」;從實際結構上來說,一個鏈表只含有一個數據甚至不含數據,他還是會有指針域和表頭,隊列/堆棧等也一樣,而這些部分就表現了「關係」。相反,單個int/char/float/double數據不含有這些表示關係的部分,所以不能算做一種特殊的 數據結構 。

最後,「數組」確實是一個令人頭疼的概念,不過我覺得應該把他算作 數據結構 的一種。依然先從定義上來看,他確實描述了一種關係,只不過剛好描述的數據一個挨一個緊密排列的關係;從實際結構上來說,我和 陳岩 看法不同,單個char/int確實和數組一樣內存上連續,但兩個char間不一定是連續的,但數組中卻一定是連續的,數組描述的正是這種緊密連續的 數據結構 數組在內存中儲存時也有末尾的多餘部分「」來描述「結束」這一關係。(關於 數組 ,一樓 狼大人 的敘述更精確)


@Liutos 的答案比較靠譜,我對數據類型做一個補充

這裡的人總是喜歡把數據在內存中怎麼存放的和類型聯繫起來,其實這兩者之間關係挺遠的。哪怕和系統很近的C語言也沒規定每個類型底層怎麼存儲,具體多少byte,大端還是小端都沒有。

數據類型的作用是限制你程序所做的事情,以檢查出潛在的錯誤。比如在靜態類型的語言比如C中,你有一個類型int的變數,那麼就限定了它是一個範圍有限的整數,你可以對它做運算,但是系統會阻止你把它當作函數調用,這可以阻止潛在的錯誤發生。而且在靜態類型的語言中,這樣的錯誤在編譯期就可以檢查出來了,免得你程序哪天跑著跑著就中槍了。因為這樣的語言變數攜帶類型,類型檢查在編譯期就完成了,所以一般值自身很少攜帶類型信息。
另外一類是動態類型系統的語言,其中變數不攜帶類型而是值攜帶類型,所以當你運行到某個地方想要把一個整數當成函數調用的時候,類型檢查就會失敗,然後你就會得到一個運行錯誤。

所以類型的作用相當於是規定程序中的一部分:值或者變數,他們可以進行什麼樣的操作。而到底是規定值還是變數,那麼就取決於什麼樣的類型系統了。


其實嚴蔚敏編著的《數據結構》已經很好的回答了這個問題。

要理解這個問題先得具備以下三個基礎概念,下方還會提及,這三個概念可以跳過不看

  1. 數據結構:是相互之間存在一種或多種特定關係的數據元素的集合,包括邏輯結構和物理結構。
  2. 數據類型:是一個值的集合和定義在這個值集上的一組操作的總稱。
  3. 抽象數據類型:是指一個數學模型以及定義在該模型上的一組操作。

解讀這三個基礎概念,也就是它們之間的關係。

數據結構和數據類型其實是所屬關係,是什麼樣的所屬關係呢?看圖:

解釋一下這張我自己繪製的圖:

一種數據結構+定義在此種數據結構上的一組操作=結構類型

一種值的集合+定義在此種值的集合上的一組操作=原子類型

結構類型+原子類型=數據類型

以下是背景知識,很重要,當然不想細看的直接看段尾的一句話總結。

三個基礎概念:

  1. 數據結構:是相互之間存在一種或多種特定關係的數據元素的集合,包括邏輯結構和物理結構。
  2. 數據類型的定義是:是一個值的集合和定義在這個值集上的一組操作的總稱。
  3. 數據類型的分類是:原子類型和結構類型。

融合2和3基礎概念和上圖可得:數據類型的兩種類型是按照定義中兩種「值的集合」來區分的。結構類型就是「值的集合」是一種數據結構,例如線性表、樹和圖;而原子類型就是「值的集合」是原子類型,例如C語言中的基本類型(整型、實型、字元型和枚舉類型)、指針類型和空類型。

一句話總結,數據結構是一種值的集合,這種值集+值集上的操作就是結構類型,而結構類型是數據類型中的一種,所以數據結構屬於數據類型。


接下來解釋數據類型和抽象數據類型的關係:

還是那句話,以下是背景知識,很重要,當然不想細看的直接看段尾的一句話總結。

兩個基礎概念:

  1. 數據類型:是一個值的集合和定義在這個值集上的一組操作的總稱。
  2. 抽象數據類型:是指一個數學模型以及定義在該模型上的一組操作。

它們的異同其實就在字面上了——抽象。

抽象數據類型的定義僅取決於它的一組邏輯特性,而與其在計算機內部如何表示和實現無關,即無論其內部結構如何變化,只要它的數學特性不變,都不影響其外部的使用。」抽象「的意義在於數據類型的數學抽象特性。

一句話總結,數據類型和抽象數據類型的相同點在於它們具有相同的邏輯特性,不同點在於數據類型即關係數據集的邏輯特性又關係其物理特性,而抽象數據類型只關心數據集的抽象特性。


總結起來就是這三條基礎概念:

  1. 數據結構:是相互之間存在一種或多種特定關係的數據元素的集合,包括邏輯結構和物理結構。
  2. 數據類型:是一個值的集合和定義在這個值集上的一組操作的總稱。
  3. 抽象數據類型:是指一個數學模型以及定義在該模型上的一組操作。

以下是班門弄斧時間:

我認為,「數據類型」是計算機發展出來的一種重要思想,它將程序設計一分為二:實現基本數據類型和使用抽象數據類型。實現基本數據類型是指在物理層面實現數據類型的邏輯特性;使用抽象數據類型是指僅僅關注數據類型的邏輯特性,而不關注硬體實現。這樣兩邊的人都可以更集中注意力於自己的工作範圍,進行更深的鑽研。


2013-10-18 全文更新

首先說下數據。
數據的本質是差異,每一種差異是一個值。數據的意義是用來對比。

接下來考慮數據的表示。
表示數據就要把所有的差異枚舉出來,也就是確定值的範圍。
最簡單的表示數據的方式是使用二值位串。這也是計算機使用的方式。位串這種東西很常見,例如阿拉伯數字。
這裡強調一點:數據沒有類型。如,「1」是一個數字還是字元?只有在被使用的時候才知道。數據的類型在於使用其的方式。人類認知事物的典型方式是加標籤,或者說分類。這種方式便於人類理解,但同樣也只是人類的主觀意願。舉個例子,一個狼人以人的形態走在路上,如何判斷他是人還是狼人。如果你告訴我狼人也是人,那我無話可說。
可能因為受到了面向對象思想的影響,我用了很長時間才意識到這一點。

接下來考慮數據的解釋。
如何判斷「123456」是一個數字還是兩個數字?這裡需要使用約定。需要事先約定好一個數字是三位還是六位。
也就是說,在解釋一組數據之前需要對數據的表示方式做好約定。

接下來考慮數據存儲。
受那位匿名同學的啟發,數據的存儲方式也就是數據結構。
回想我們在數據結構課上學到的東西,數據結構考慮的通常是效率和空間這些問題。而這些東西絕對是由數據的存儲方式決定的。通常一種高效的演算法會使用專門為這種演算法設計的數據結構。這也就是數據結構的意義。

如果一定要問數據類型是什麼東西,只能說是一種人為的限制。
可能最開始數據類型出現的目的是為了減少由於程序員不小心造成的錯誤。還有可能就是受到面向對象思想的影響。或者乾脆就是別人有我也應該有的想法。


我覺得糾結這兩個概念細微差異的意義不大,因為數據結構(data structure)和數據類型(data type)有著不同的使用語境和指代對象,只需要分清其各自表示什麼和該怎麼用即可。在以後的工作科研中沒人會熱衷區分這兩個概念。

先說數據結構(data structure)。一般來說數據結構指的都是結構化的東西,也就是說若干elements(這個詞不好翻譯,可以認為是基本元素)按照一定結構組成的。如數組,鏈表。可以看出這兩種都是由基本元素組成,而且形成一定結構(數組是物理內存連續,鏈表是用指針相連)。而組成的elements可以是複雜結構,如一個結構體組成的數組,或者有嵌套結構的elements。

數據類型(data type)強調類型,一般分為兩種,基本數據類型(int char等)和複雜數據類型(結構體等)。基本結構對應基本數據類型(如一個字元對應char型),複雜結構對應複雜數據類型(結構體)。這個概念是可以對應上面數據結構中的elements的類型。

想總結一下,數據放在elements中,每個elements一般都是線性地址相連的存儲,elements的類型叫數據類型,由elements組成的更複雜的結構叫做數據結構。


補充一下,我覺得原子分子的比喻是不恰當的。確切的說,數據應該是原子,數據結構是分子。數據結構由數據組成(一般的數據結構的直接組成部分只有一種類型的數據)。而數據由於其表達方式不同,有著不同的數據類型,數據類型用來區分和表達不同元素。

理解這兩個概念必須從數據入手,數據可以認為是在線性內存中連續存儲的一段信息,這段信息在內存中不過就是不加區分的01串而已。而數據類型是讓編程者和編譯器識別這段數據表達方式的一種定義。數據結構是將數據用某種方式組合起來的一種結構。所以數據才是核心。


數據結構是數據與數據之間的關係,數據類型是數據的種類。


貌似數據結構中包含了數據類型,而數據類型又建立在數據結構之上?
就像有人在其他評論里說的,數據本質上是沒有類型的。我們都知道,數據在存儲上是一堆01的數字,有時候我們要拿4個位元組(int),有時候要拿1個位元組(char),有時候又是8個位元組(double);又有時候我們要拿第一個存進去的(FIFO),或者拿最新放進去的(LIFO),有時候又要拿最大的、最小的(heap),等等等。所以,數據結構是對數據的一種操作方式,定義了如何存取就定義了數據結構。至於數據類型?who care?你愛叫阿貓阿狗都可以。數據類型只是一個名稱,它既可以包含在數據結構里,又可以命名數據結構。

那麼數組到底是一種數據結構還是一種數據類型呢?
數組只是個名稱,它可以描述一組操作,也可以命名這組操作。數組的數據操作,是通過index--&>value來實現的。它不是具體要求內存上要存儲著連續的數據才叫數據,而是說,通過連續的索引index,我可以訪問相鄰的數據。具體可參考c的數組實現、php的數組實現......

是不是除了線性表、隊列、堆棧、樹......這些,int char double也可以看成一種簡單的只有一個數據元素的數據結構呢?
是的,還是那句話,你定義了數據的存取你就定義了數據結構。


大言不慚地說,其它答案都沒搞懂(逃

數據結構強調結構,即元素間的關係
數據類型強調類型,即作用於元素的合法操作


數據類型是值的集合及對這些值的運算
數據結構是數據元素的關係及對這種關係的操作。數據元素是有類型的,但是數據結構撇開了這種元素具體的類型,只考慮數據元素間的相互關係。
數組是數據結構也是數據類型,要看你用什麼角度看
int a[3]; 這裡的a的類型是int [3]
但若是
typedef int DATATYPE;
DATATYPE a[3];
只要是你不需要考慮 DATATYPE 具體是什麼類型的時候
這裡的a就是一種數據結構


用積木來打個比方:
每一種積木塊都可以看作是一種「積木類型」。
把這些積木塊按照一定的規則拼在一起就有了「積木結構」。
現在,把積木換成數據。


數據結構 = 數據 + 組成方式;
數據類型 = 數據 + 處理方式。


二者的定義不用說了,百科都有,

個人覺得,數據類型偏向於用途用法方面,比如整型我用來計算,做加減乘除,字元串我用來表示文字信息,可以截取,拼接;

數據結構偏向其內部原理,如鏈表的實現鏈式存儲,隊列用來保存待處理的數據等;

就說數組吧,我寫 int[10] arr_data;的時候,我說arr_data是一個數組,這裡的數組是說的是數據類型,

我說這些數據用一個數組做成線性表存儲的時候,這裡的數組說的是數據結構。


數據結構是數據的一種表現形式,我們把一個具體的人當做一個數據,這人都是由一個頭兩條腿組成。這頭跟腿可以看成是具體的這個人的組成的數據項,他們的關係是頭是在上面的腿是在下面的,所以具體的某個人這個數據的表現形式是頭在上面兩條腿在下面。而每個人都有這樣的表現形式也就是都有這樣的相同的數據結構,我們把每個具體的人歸為同一類,把它叫做人類這種數據類型。這數據類型也可以看成是數據的一個屬性,每個數據都有這樣的一個屬性。int a[3],int b[4]這a和b的數據類型的屬性是相同的嗎?他們的表現形式(數據結構)是一樣的嗎??我的回答是都不一樣,a跟b一個是由3個連接的int組成,一個是由4個連接的int組成。如果拿人來做比較,其它所有的構成都一樣,但一個是1顆腦袋,一個是2顆腦袋,那這兩個我們會把它當成是相同的數據結構嗎?數據結構都不同,那它們自然是不屬於同一個數據類型了。在我看來數組類型,結構體類型是一個很大的概念,就像基本類型一樣,我們可以說int是屬於基本類型的,char也是屬於基本類型的。但int跟char這兩個不是屬於同一個類型的。而int [3]這是屬於數組類型,int [4]也是屬於數組類型,但它們不是屬於同一個數據類型。這有點像我們定義的類,我們用類聲明的對象都是屬於類類型,但類類型這個大的類型底下又分了無窮個自定義的類型


先說數據類型,這個從字面上就可以理解。比如我們常用的字元型(string/varchar),數值型(number/int/double),布爾型(boolean),日期(date/datetime)等等。這些是用來標註一個變數或者資料庫中的一個欄位是什麼類型,儲存什麼樣的值的。比如說你定義了一個變數叫vUpdateDate,會給它指定日期類型,就只能給它賦日期型的值。

而數據類型,就像書里說的,是一些數據元素的集合。這些數據元素可以是同一類型,也可以是不同類型的。舉例說明,相同類型的數據結構,比如數組,裡面可以存儲同樣的值,比如一個班級里所有學生的名字或者學號。而不同類型的數據結構,往往需要自己定義。比如定義一個數據結構存儲一個產品的相關屬性:產品編號,產品名稱,產品大小(長寬高),產品價格,生產日期等等。而這樣的數據結構也可以定義成類(class),這樣這個產品類也可以作為類型來使用了。

希望能有幫助!


數據類型:一個數據集以及作用於此數據集上的運算集構成的系統。數據類型包含抽象層和實現層兩個層次,抽象層為抽象數據類型(即數據類型的定義),實現層為C++、Java等語言實現的類(即數據類型的實現)。

數據結構:一組數據單元按某種離散的結構關係構成的系統。數據結構也包含抽象層和實現層兩個層次,抽象層為線性結構、樹形結構等離散結構,實現層為順序存儲結構、鏈接存儲結構等存儲結構。

兩者的聯繫:數據結構的抽象層和實現層分別用於定義和實現數據類型的數據集。簡而言之就是,抽象數據類型 = 離散結構 + 介面,類 = 存儲結構 + 函數。

本人才疏學淺,若回答中有錯漏之處,還請各位知友批評指正。


個人愚見,雖然不一定完全正確,但是比較好統一這些教科書中天書般的概念!


數據類型:類(指廣義上的對象類,包括自定義類,int,float,char...)

數據結構:類之間的邏輯關係(包括類的集合,線性表,堆棧,隊列,樹,圖...),

類之間的物理關係(包括數組和鏈表)

ps:數據結構一般重點指邏輯關係,物理關係只是具體計算機中的實現方式

介面:數據類型(或者類)的抽象,不用給具體實現

抽象數據類型:數據結構的抽象,不給具體實現


2017-05-11

好像有新的理解,

用面向對象的思想看,抽象數據類型就是介面,數據結構就類


數據結構描述的是數據之間的關係,如線性關係,圖狀關係等;

抽象數據類型規定了一個數學模型即對這個模型的一系列操作,如棧以及對棧的push及pop操作。


本質就是,沒有明確定義,很可能就是一樣的。你玩這種思維遊戲就是浪費美麗的人生。


這樣子說吧:
我們經常可以看到定義一個類型:
typedef struct {
int x;
int y;
}point;

分解一下:
數據結構:struct { int x; int y;};
數據類型:typedef .... point;

我想這是對程序員寫代碼時最直觀的感受。


推薦閱讀:

自學看書煩了你們怎麼應對?很煩躁
遊戲場景管理的八叉樹演算法是怎樣的?
如何學習數據結構?

TAG:軟體 | 編程 | 數據結構 |