打算把數(shù)據(jù)結(jié)構(gòu)跟算法的知識捋一捋,所以新建了個文集。
很多人都說這是內(nèi)功,那學(xué)這個到底有什么用呢,我找了幾篇蠻有道理的文章轉(zhuǎn)了過來,來堅定下學(xué)習(xí)的信念。
我看完這幾篇后覺得,學(xué)這個最重要的是學(xué)會了把現(xiàn)實中的實際問題抽象為計算機能夠理解的數(shù)據(jù)模型,然后施加以算法以解決問題。
找的文章如下:
作者:劉欣
鏈接:https://www.zhihu.com/question/29587605/answer/147424220
來源:知乎
《數(shù)據(jù)結(jié)構(gòu)》是計算機專業(yè)的一門必修課, 可是很多學(xué)生學(xué)完以后,覺得用處不大, 還不如學(xué)個C,Java來的直接一點。
等到工作了以后做業(yè)務(wù)系統(tǒng)開發(fā),發(fā)現(xiàn)根本就用不到那些書中的講的二叉樹、圖、排序算法, 更加覺得這門課是在浪費時間了。
這種想法實際上是錯誤的。
學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu),并不僅僅是學(xué)習(xí)其中現(xiàn)成的那些隊列,堆棧,二叉樹,圖等經(jīng)典結(jié)構(gòu), 也不僅僅是學(xué)習(xí)其中的那些快速排序、冒泡排序等算法。
更重要的是你要學(xué)習(xí)一種思想:如何把現(xiàn)實問題轉(zhuǎn)化為計算機語言的表示。
計算機其實一種很笨,很機械的機器,只會按照預(yù)定的指令一步步執(zhí)行, 而計算機語言的特點就是精確、無二意, 它的本質(zhì)語言是二進制的, 即使是C,Java等高級一點的語言也只不過是包裝而已, 它的表達能力并沒有本質(zhì)的提升, 仍然停留在很低的層次。
而我們用的自然語言則是典型的模糊的,不精確的, 程序員面臨的一個重要問題, 或者是我們的主要工作就是怎么把自然語言描述的問題轉(zhuǎn)化為計算機語言的表示。
到底該怎么轉(zhuǎn)化, 《數(shù)據(jù)結(jié)構(gòu)》已經(jīng)給出了指引: 設(shè)計出數(shù)據(jù)結(jié)構(gòu), 在施加以算法就行了, 當(dāng)然現(xiàn)實問題會更復(fù)雜, 需要框架,類庫,模式等支撐。
這是一種非常重要的邏輯思維能力的鍛煉, 也是程序員入門的條件。
很多半路出家的人, 僅僅上了個培訓(xùn)班后參加工作, 寫出的代碼實在是慘不忍睹, 很明顯只掌握了工具,邏輯思維的訓(xùn)練遠遠不足。
就我個人而言, 大學(xué)時學(xué)《數(shù)據(jù)結(jié)構(gòu)》以后, 為了準備高級程序員考試, 把里邊的習(xí)題全部做了一遍, 發(fā)現(xiàn)真是受益匪淺, 不但高程的成績非常好, 更重要的是在后來的工作中,遇到數(shù)據(jù)結(jié)構(gòu)相關(guān)的實際問題, 基本上沒有什么障礙,只要掌握了語言特性, 解決起來非常輕松。
總結(jié)一下,《數(shù)據(jù)結(jié)構(gòu)》這門課其實會潛移默化的影響你的邏輯思維, 當(dāng)然, 你需要多多練習(xí)才有可能使用純熟, 等它變成身體一部分以后, 你就發(fā)現(xiàn)其實大部分編程任務(wù)都沒什么難度了,更難的其實是對編程更高的要求:抽象的能力。
作者:呂雙全
鏈接:https://www.zhihu.com/question/29587605/answer/71567673
來源:知乎
想從“由頂向下”的角度說說自己淺顯的理解:
我們知道計算機是人類在思考“能不能偷懶”的原始欲望下創(chuàng)造出來——找一個自動、快速、不知疲憊地替人類進行各種工作的機器。在有了諸如“圖靈機”等計算模型理論的支撐下,人們找到了通用的底層方式來實現(xiàn)自己想要功能的方法。但這些方法需要讓計算機理解——或者可以被處理后理解,就需要我們以某種形式,將我們的問題一步步抽象、一步步化簡,直到形成某種計算機可以理解的“程式化”的語言或組織形式,最后對計算機說一句:剩下的就交給你了!
舉個不甚恰當(dāng)?shù)睦樱?br> 比如我們計劃去旅游,我們手里有地圖,想知道計劃中的幾個城市直接是否都有高速公路可以走,從而不會有某個城市因道路不通而無法驅(qū)車前往。雖然我們可以自己去查,但是我們有計算機啊!于是我們想借助它來完成這個任務(wù),于是進行了第一步抽象——將城市表示為一個個點,道路表示為邊,結(jié)合起來形成了叫圖的數(shù)據(jù)結(jié)構(gòu)。我們想知道的便是——這張圖是否是一個連通圖?比如我們用1、2、3、4分別表示“北上廣深”(僅作意會),線段表示道路,于是有了這張圖:
畫出來以后,我們自己心里明白它表示什么,但計算機不懂。于是我們進行第二步抽象——將圖編碼,轉(zhuǎn)化為計算機可以編譯的語言。于是得到下面表示方式:
<G> = (1,2,3,4) ((1,2),(2,3),(3,1),(1,4))
前面括號中我們用數(shù)字表示各個節(jié)點(對應(yīng)“城市”)的編號,后面則用“(節(jié)點,節(jié)點)”成對的形式表示一條邊(對應(yīng) “道路”)。
那么計算機如何處理呢?這時就需要設(shè)計一種算法,告訴它怎么理解和處理人類跟你說的話。比如可以按這樣的方式:
- 選擇第一個節(jié)點并進行標記。
- 重復(fù)第3步直到?jīng)]有新的節(jié)點可以被標記。
- 對于G中的每個節(jié)點Ni,如果有一條邊與其相連,且邊的另一頭是一個已經(jīng)被標記的節(jié)點Nj(i不等于j),那么將Ni進行標記。(這一步要借助上面寫出的“邊的集合”((1,2),(2,3),(3,1),(1,4)))
- 掃描一遍點的集合(這里是(1,2,3,4)),如果都被標記了,那么就是連通圖(對應(yīng)“每個城市都有道路經(jīng)過”);否則不是。
當(dāng)計算機運行之后,我們開心的發(fā)現(xiàn),得出了想要的結(jié)果。更開心的是它不僅可以對這幾個城市查詢道路,還可以對更多的城市做同樣的查詢!我們因此省去了自己人工查詢的繁瑣。
具體如何實現(xiàn)這個算法還要涉及更底層的方面,不過我想到這里數(shù)據(jù)結(jié)構(gòu)與算法已經(jīng)體現(xiàn)出來了——正是有了這兄弟倆,我們才能讓借助計算機來得到想要的東西,從而大大方便我們的生活,以及創(chuàng)造出如此眾多神奇的科技。
愈往深處和廣處學(xué)習(xí),愈覺得人類智慧的偉大。
數(shù)據(jù)結(jié)構(gòu)與算法,正是前人在計算機領(lǐng)域智慧結(jié)晶的集中領(lǐng)域之一,我想有時甚至不需要知道學(xué)好它有什么用,因為體悟智慧本身不就是一種享受嗎?
作者:猴鼻帕5
鏈接:https://zhidao.baidu.com/question/1951067610918494068.html
來源:百度知道
本人乃一個數(shù)據(jù)癡迷者,在計算機的道路上,也是一個數(shù)據(jù)結(jié)構(gòu)的癡迷者,現(xiàn)在大學(xué)里面和同學(xué)搞開發(fā)也癡迷于數(shù)據(jù)庫,我就我個人的理解給你談一談:
首先,數(shù)據(jù)結(jié)構(gòu)是一門計算機語言學(xué)的基礎(chǔ)學(xué)科,它不屬于任何一門語言,其體現(xiàn)的是幾乎所有標準語言的算法的思想。
上面的概念有一些模糊,我們現(xiàn)在來具體說一說,相信你們的數(shù)據(jù)結(jié)構(gòu)使用的是一門具體的語言比如C/C++語言來說明,那是為了輔助的學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu),而數(shù)據(jù)結(jié)構(gòu)本身不屬于任何語言(相信你把書上的程序敲到電腦里面是不能通過的吧,其只是描述了過程,要調(diào)試程序,還需要修改和增加一些東西)。
你們的書上開始應(yīng)該在講究數(shù)據(jù)的物理存儲結(jié)構(gòu)/邏輯存儲結(jié)構(gòu)等概念,說明數(shù)據(jù)結(jié)構(gòu)首先就是“數(shù)據(jù)的結(jié)構(gòu)”,在內(nèi)存上的存儲方式,就是物理的存儲結(jié)構(gòu),在程序使用人員的思想上它是邏輯的,比如:
你們在C/C++中學(xué)習(xí)到鏈表,那么鏈表是什么一個概念,你們使用指針制向下一個結(jié)點的首地址,讓他們串聯(lián)起來,形成一個接一個的結(jié)點,就像顯示生活中的火車一樣。而這只是對于程序員的概念,但是在內(nèi)存中存儲的方式是怎樣的那?對于你程序員來說這是“透明”的,其內(nèi)部分配空間在那里,都是隨機的,而內(nèi)存中也沒有一個又一根的線將他們串聯(lián)起來,所以,這是一個物理與邏輯的概念,對于我們程序員只需要知道這些就可以了,而我們主要要研究的是“邏輯結(jié)構(gòu)”。
我可以給你一個我自己總結(jié)的一個概念:所有的算法必須基于數(shù)據(jù)結(jié)構(gòu)生存。也就是說,我們對于任何算法的編寫,必須依賴一個已經(jīng)存在的數(shù)據(jù)結(jié)構(gòu)來對它進行操作,數(shù)據(jù)結(jié)構(gòu)成為算法的操作對象,這也是為什么算法和數(shù)據(jù)結(jié)構(gòu)兩門分類不分家的概念,算法在沒有數(shù)據(jù)結(jié)構(gòu)的情況下,沒有任何存在的意義;而數(shù)據(jù)結(jié)構(gòu)沒有算法就等于是一個尸體而沒有靈魂。
估計這個對于算法的初學(xué)者可能有點暈,我們在具體的說一些東西吧:我們在數(shù)據(jù)結(jié)構(gòu)中最簡單的是什么:我個人把書籍中線性表更加細化一層(這里是為了便于理解在這樣說的):
單個元素,比如:int i;這個i就是一個數(shù)據(jù)結(jié)構(gòu),它是一個什么樣的數(shù)據(jù)結(jié)構(gòu),就是一個類型為int的變量,我們可以對它進行加法/減法/乘法/除法/自加等等一系列操作,當(dāng)然對于單個元素我們對它的數(shù)據(jù)結(jié)構(gòu)和算法的研究沒有什么意義,因為它本來就是原子的,某些具體運算上可能算法存在比較小的差異;
而提升一個層次:就是我們的線性表(一般包含有:順序表/鏈表)那么我們研究這樣兩種數(shù)據(jù)結(jié)構(gòu)主要就是要研究它的什么東西那?一般我們主要研究他們以結(jié)構(gòu)為單位(就是結(jié)點)的增加/刪除/修改/檢索(查詢)四個操作(為什么有這樣的操作,我在下面說到),我們一般把“增加/刪除/修改”都把它稱為更新,對于一個結(jié)點,若要進行更新一類的操作比如:刪除,對于順序表來說是使用下標訪問方式,那么我們在刪除了一個元素后需要將這個元素后的所有元素后的所有元素全部向前移動,這個時間是對于越長的順序表,時間越長的,而對于鏈表,沒有順序的概念,其刪除元素只需要將前一個結(jié)點的指針指向被刪除點的下一個結(jié)點,將空間使用free()函數(shù)進行釋放,還原給操作系統(tǒng)。當(dāng)執(zhí)行檢索操作的時候,由于順序表直接使用下標進行隨機訪問,而鏈表需要從頭開始訪問一一匹配才可以得到使用的元素,這個時間也是和鏈表的結(jié)點個數(shù)成正比的。
所以我們每一種數(shù)據(jù)結(jié)構(gòu)對于不同的算法會產(chǎn)生不同的效果,各自沒有絕對的好,也沒有絕對的不好,他們都有自己的應(yīng)用價值和方式;這樣我們就可以在實際的項目開發(fā)中,對于內(nèi)部的算法時間和空間以及項目所能提供的硬件能力進行綜合評估,以讓自己的算法能夠更加好。
(在這里只提到了基于數(shù)據(jù)結(jié)構(gòu)的一個方面就是:速度,其實算法的要素還應(yīng)該包括:穩(wěn)定性、健壯性、正確性、有窮性、可理解性、有輸入和輸出等等)
為什么要以結(jié)點方式進行這些亂七八糟的操作那?首先明確一個概念就是:對于過程化程序設(shè)計語言所提供的都是一些基礎(chǔ)第一信息,比如一些關(guān)鍵字/保留字/運算符/分界符。
而我們需要用程序解決現(xiàn)實生活中的問題,比如我們要程序記錄某公司人員的情況變化,那么人員這個數(shù)據(jù)類型,在程序設(shè)計語言中是沒有的,那么我們需要對人員的內(nèi)部信息定義(不可能完全,只是我們需要那些就定義那些),比如:年齡/性別/姓名/出生日期/民族/工作單位/職稱/職務(wù)/工資狀態(tài)等,那么就可以用一些C/C++語言描述了,如年齡我們就可以進行如下定義:
int age;/age變量,表示人員公司人員的年齡/
同理進行其他的定義,我們用結(jié)構(gòu)體或類把他們封裝成自定義數(shù)據(jù)類型或類的形式,這樣用他們定義的就是一個人的對象的了,它內(nèi)部包含了很多的模板數(shù)據(jù)了。
不知道你看完后,有沒有新的收獲?