堆棧有哪兩種基本操作它的含義是什么(堆棧有哪兩種基本操作它的含義是什么和什么)
作者:you6 來(lái)源:天游快遞 2023-09-30 16:17:03
?
數(shù)據(jù)結(jié)構(gòu)主要研究什么?
?
數(shù)據(jù)結(jié)構(gòu)作為一門學(xué)科主要研究數(shù)據(jù)的各種邏輯結(jié)構(gòu)和備猛存儲(chǔ)結(jié)構(gòu),以及對(duì)數(shù)據(jù)的各種操作。因此,主要有三個(gè)方面的內(nèi)容:數(shù)據(jù)的邏輯結(jié)構(gòu);數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu);對(duì)數(shù)據(jù)的操作(或算法)。通常,算法的
?
設(shè)計(jì)取決于數(shù)據(jù)的邏輯結(jié)構(gòu),算法的實(shí)現(xiàn)取決于數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu)。
?
什么是數(shù)據(jù)結(jié)構(gòu)?什么是邏輯結(jié)構(gòu)和物理結(jié)構(gòu)?
?
數(shù)據(jù)是指由有限的符號(hào)(比如,"0"和"1",具有其自己的結(jié)構(gòu)、操作、和相應(yīng)的語(yǔ)義)組成的元素的集合。結(jié)構(gòu)是元素之間的關(guān)系的集合。通常來(lái)說(shuō),一個(gè)數(shù)據(jù)結(jié)構(gòu)DS 可以表示為一個(gè)二元組:
?
DS=(D,S), //i.e., datastructure=(datapart,logicstructurepart) 這里D是數(shù)據(jù)元素的集合(或者是“結(jié)點(diǎn)”,可能還含有“數(shù)據(jù)項(xiàng)”或“數(shù)據(jù)域”),S是定義在D(或其他集合)上的關(guān)系的集合,S = ,稱之為元素的邏輯結(jié)構(gòu)。 邏輯結(jié)構(gòu)有四種基本類型:集合結(jié)構(gòu)、線性結(jié)構(gòu)、樹狀結(jié)構(gòu)和網(wǎng)絡(luò)結(jié)構(gòu)。表和樹是最常用的兩種高效數(shù)據(jù)結(jié)構(gòu),許多高效的算法可以用這兩種數(shù)據(jù)結(jié)構(gòu)來(lái)設(shè)計(jì)實(shí)現(xiàn)。表是線性結(jié)構(gòu)的(全序關(guān)系),樹(偏序或?qū)哟侮P(guān)系)和圖(局部有序(weak/local orders))是非線性結(jié)構(gòu)。
?
數(shù)據(jù)結(jié)構(gòu)的物理結(jié)構(gòu)是指邏輯結(jié)構(gòu)的存儲(chǔ)鏡像(image)。數(shù)據(jù)結(jié)構(gòu) DS 的物理結(jié)構(gòu) P對(duì)應(yīng)于從 DS 的數(shù)據(jù)元素到存儲(chǔ)區(qū)M(維護(hù)著邏輯結(jié)構(gòu)S)的一個(gè)映射:
?
(PD,S) > M 存儲(chǔ)器模型:一個(gè)存儲(chǔ)器 M 是一系列固定大小的存儲(chǔ)單元,每個(gè)單元 U 有一個(gè)唯一的地址 A(U),該地址被連續(xù)地編碼。每個(gè)單元 U 有一個(gè)唯一的后繼單元 U'=succ(U)。 P 的四種基本映射模型:順序(sequential)、鏈接(linked)、索引(indexed)和散列(hashing)映射。
?
因此,我們至少可以得到4×4種可能的物理數(shù)據(jù)結(jié)構(gòu):
?
sequential (sets)
linked lists
indexed trees
hash graphs
?
(并不是所有的可能組合都合理)
?
??? 數(shù)據(jù)結(jié)構(gòu)DS上的操作:所有的定義在DS上的操作在改變數(shù)據(jù)元素(節(jié)點(diǎn))或節(jié)點(diǎn)的域時(shí)必須保持DS的邏輯和物理結(jié)構(gòu)。
?
DS上的基本操作:任何其他對(duì)DS的高級(jí)操作都可以用這些基本操作來(lái)實(shí)現(xiàn)。最好將DS和他的所有基本操作看作一個(gè)整體——稱之為模塊。我們可以進(jìn)一步將該模塊抽象為數(shù)據(jù)類型(其中DS的存儲(chǔ)結(jié)構(gòu)被表示為私有成員,基本操作被表示為公共方法),稱之為ADT。作為ADT,堆棧和隊(duì)列都是一種特殊的表,他們擁有表的操作的子集。 對(duì)于DATs的高仿告橋級(jí)操作可以被設(shè)計(jì)為(不封裝的)算法,利用基本操作對(duì)DS進(jìn)行處理。
?
好的和壞的DS:如果一個(gè)DS可以通過(guò)某種“線性規(guī)則”被轉(zhuǎn)化為線性的DS(例如線性表),則稱它為好的DS。好的DS通常對(duì)應(yīng)于好的(高效的)算法。這是由計(jì)算機(jī)的計(jì)算能力決定的,因?yàn)橛?jì)算機(jī)本質(zhì)上只能存取邏輯連續(xù)的內(nèi)存單元,因此如何沒(méi)有線性化的結(jié)構(gòu)邏輯上是不可計(jì)算的。比如對(duì)一個(gè)圖進(jìn)行操作,要訪問(wèn)圖的所有結(jié)點(diǎn),則必須按照某種順序來(lái)依次訪問(wèn)所有節(jié)點(diǎn)(要形成一個(gè)偏序),必須通過(guò)某種方式將圖固有的非線性結(jié)構(gòu)轉(zhuǎn)化為線性結(jié)構(gòu)才能對(duì)圖進(jìn)行操作。
?
樹是好的DS——它有非常簡(jiǎn)單而高效的線性化規(guī)則,因此可以利用樹設(shè)計(jì)出許多非常高效的算法。樹的實(shí)現(xiàn)和使用都很簡(jiǎn)單,但可以解決大量特殊的復(fù)雜問(wèn)題,因此樹是實(shí)際編程中最重要和最有用的一種數(shù)據(jù)結(jié)構(gòu)。樹的結(jié)構(gòu)本質(zhì)上有遞歸的性質(zhì)友胡——每一個(gè)葉節(jié)點(diǎn)可以被一棵子樹所替代,反之亦然。實(shí)際上,每一種遞歸的結(jié)構(gòu)都可以被轉(zhuǎn)化為(或等價(jià)于)樹形結(jié)構(gòu)。
?
從機(jī)器語(yǔ)言到高級(jí)語(yǔ)言的抽象
?
我們知道,算法被定義為一個(gè)運(yùn)算序列。這個(gè)運(yùn)算序列中的所有運(yùn)算定義在一類特定的數(shù)據(jù)模型上,并以解決一類特定問(wèn)題為目標(biāo)。這個(gè)運(yùn)算序列應(yīng)該具備下列四個(gè)特征。 有限性,即序列的項(xiàng)數(shù)有限,且每一運(yùn)算項(xiàng)都可在有限的時(shí)間內(nèi)完成;確定性,即序列的每一項(xiàng)運(yùn)算都有明確的定義,無(wú)二義性;可以沒(méi)有輸入運(yùn)算項(xiàng),但一定要有輸出運(yùn)算項(xiàng);可行性,即對(duì)于任意給定的合法的輸入都能得到相應(yīng)的正確的輸出。這些特征可以用來(lái)判別一個(gè)確定的運(yùn)算序列是否稱得上是一個(gè)算法。 但是,我們現(xiàn)在的問(wèn)題不是要判別一個(gè)確定的運(yùn)算序列是否稱得上是一個(gè)算法,而是要對(duì)一個(gè)己經(jīng)稱得上是算法的運(yùn)算序列,回顧我們?cè)?jīng)如何用程序設(shè)計(jì)語(yǔ)言去表達(dá)它。
?
算法的程序表達(dá),歸根到底是算法要素的程序表達(dá),因?yàn)橐坏┧惴ǖ拿恳豁?xiàng)要素都用程序清楚地表達(dá),整個(gè)算法的程序表達(dá)也就不成問(wèn)題。
?
作為運(yùn)算序列的算法,有三個(gè)要素。 作為運(yùn)算序列中各種運(yùn)算的運(yùn)算對(duì)象和運(yùn)算結(jié)果的數(shù)據(jù);運(yùn)算序列中的各種運(yùn)算;運(yùn)算序列中的控制轉(zhuǎn)移。這三種要素依序分別簡(jiǎn)稱為數(shù)據(jù)、運(yùn)算和控制。 由于算法層出不窮,變化萬(wàn)千,其中的運(yùn)算所作用的對(duì)象數(shù)據(jù)和所得到的結(jié)果數(shù)據(jù)名目繁多,不勝枚舉。最簡(jiǎn)單最基本的有布爾值數(shù)據(jù)、字符數(shù)據(jù)、整數(shù)和實(shí)數(shù)數(shù)據(jù)等;稍復(fù)雜的有向量、矩陣、記錄等數(shù)據(jù);更復(fù)雜的有集合、樹和圖,還有聲音、圖形、圖像等數(shù)據(jù)。 同樣由于算法層出不窮,變化萬(wàn)千,其中運(yùn)算的種類五花八門、多姿多彩。最基本最初等的有賦值運(yùn)算、算術(shù)運(yùn)算、邏輯運(yùn)算和關(guān)系運(yùn)算等;稍復(fù)雜的有算術(shù)表達(dá)式和邏輯表達(dá)式等;更復(fù)雜的有函數(shù)值計(jì)算、向量運(yùn)算、矩陣運(yùn)算、集合運(yùn)算,以及表、棧、隊(duì)列、樹和圖上的運(yùn)算等:此外,還可能有以上列舉的運(yùn)算的復(fù)合和嵌套。 關(guān)于控制轉(zhuǎn)移,相對(duì)單純。在串行計(jì)算中,它只有順序、分支、循環(huán)、遞歸和無(wú)條件轉(zhuǎn)移等幾種。
?
我們來(lái)回顧一下,自從計(jì)算機(jī)問(wèn)世以來(lái),算法的上述三要素的程序表達(dá),經(jīng)歷過(guò)一個(gè)怎樣的過(guò)程。
?
最早的程序設(shè)計(jì)語(yǔ)言是機(jī)器語(yǔ)言,即具體的計(jì)算機(jī)上的一個(gè)指令集。當(dāng)時(shí),要在計(jì)算機(jī)上運(yùn)行的所有算法都必須直接用機(jī)器語(yǔ)言來(lái)表達(dá),計(jì)算機(jī)才能接受。算法的運(yùn)算序列包括運(yùn)算對(duì)象和運(yùn)算結(jié)果都必須轉(zhuǎn)換為指令序列。其中的每一條指令都以編碼(指令碼和地址碼)的形式出現(xiàn)。與算法語(yǔ)言表達(dá)的算法,相差十萬(wàn)八千里。對(duì)于沒(méi)受過(guò)程序設(shè)計(jì)專門訓(xùn)練的人來(lái)說(shuō),一份程序恰似一份"天書",讓人看了不知所云,可讀性
?
極差。
?
用機(jī)器語(yǔ)言表達(dá)算法的運(yùn)算、數(shù)據(jù)和控制十分繁雜瑣碎,因?yàn)闄C(jī)器語(yǔ)言所提供的指令太初等、原始。機(jī)器語(yǔ)言只接受算術(shù)運(yùn)算、按位邏輯運(yùn)算和數(shù)的大小比較運(yùn)算等。對(duì)于稍復(fù)雜的運(yùn)算,都必須一一分解,直到到達(dá)最初等的運(yùn)算才能用相應(yīng)的指令替代之。機(jī)器語(yǔ)言能直接表達(dá)的數(shù)據(jù)只有最原始的位、字節(jié)、和字三種。算法中即使是最簡(jiǎn)單的數(shù)據(jù)如布爾值、字符、整數(shù)、和實(shí)數(shù),也必須一一地映射到位、字節(jié)和字
中,還得一一分配它們的存儲(chǔ)單元。對(duì)于算法中有結(jié)構(gòu)的數(shù)據(jù)的表達(dá)則要麻煩得多。機(jī)器語(yǔ)言所提供的控制轉(zhuǎn)移指令也只有無(wú)條件轉(zhuǎn)移、條件轉(zhuǎn)移、進(jìn)入子程序和從子程序返回等最基本的幾種。用它們來(lái)構(gòu)造循環(huán)、形成分支、調(diào)用函數(shù)和過(guò)程得事先做許多的準(zhǔn)備,還得靠許多的技巧。 直接用機(jī)器語(yǔ)言表達(dá)算法有許多缺點(diǎn)。
?
大量繁雜瑣碎的細(xì)節(jié)牽制著程序員,使他們不可能有更多的時(shí)間和精力去從事創(chuàng)造性的勞動(dòng),執(zhí)行對(duì)他們來(lái)說(shuō)更為重要的任務(wù)。如確保程序的正確性、高效性。程序員既要駕馭程序設(shè)計(jì)的全局又要深入每一個(gè)局部直到實(shí)現(xiàn)的細(xì)節(jié),即使智力超群的程序員也常常會(huì)顧此失彼,屢出差錯(cuò),因而所編出的程序可靠性差,且開發(fā)周期長(zhǎng)。 由于用機(jī)器語(yǔ)言進(jìn)行程序設(shè)計(jì)的思維和表達(dá)方式與人們的習(xí)慣大相徑庭,只有經(jīng)過(guò)
較長(zhǎng)時(shí)間職業(yè)訓(xùn)練的程序員才能勝任,使得程序設(shè)計(jì)曲高和寡。因?yàn)樗臅嫘问饺?密"碼,所以可讀性差,不便于交流與合作。因?yàn)樗鼑?yán)重地依賴于具體的計(jì)算機(jī),所以可移植性差,重用性差。這些弊端造成當(dāng)時(shí)的計(jì)算機(jī)應(yīng)用未能迅速得到推廣。
?
克服上述缺點(diǎn)的出路在于程序設(shè)計(jì)語(yǔ)言的抽象,讓它盡可能地接近于算法語(yǔ)言。 為此,人們首先注意到的是可讀性和可移植性,因?yàn)樗鼈兿鄬?duì)地容易通過(guò)抽象而得到改善。于是,很快就出現(xiàn)匯編語(yǔ)言。這種語(yǔ)言對(duì)機(jī)器語(yǔ)言的抽象,首先表現(xiàn)在將機(jī)器語(yǔ)言的每一條指令符號(hào)化:指令碼代之以記憶符號(hào),地址碼代之以符號(hào)地址,使得其含義顯現(xiàn)在符號(hào)上而不再隱藏在編碼中,可讓人望"文"生義。其次表現(xiàn)在這種語(yǔ)言擺脫了具體計(jì)算機(jī)的限制,可在不同指令集的計(jì)算機(jī)上運(yùn)行,只要該計(jì)算機(jī)配上匯編語(yǔ)言的一個(gè)匯編程序。這無(wú)疑是機(jī)器語(yǔ)言朝算法語(yǔ)言靠攏邁出的一步。但是,它離算法語(yǔ)言還太遠(yuǎn),以致程序員還不能從分解算法的數(shù)據(jù)、運(yùn)算和控制到匯編才能直接表達(dá)的指令等繁雜瑣碎的事務(wù)中解脫出來(lái)。 到了50年代中期,出現(xiàn)程序設(shè)計(jì)的高級(jí)語(yǔ)言如Fortran,Algol60,以及后來(lái)的PL/l, Pascal等,算法的程序表達(dá)才產(chǎn)生一次大的飛躍。
?
誠(chéng)然,算法最終要表達(dá)為具體計(jì)算機(jī)上的機(jī)器語(yǔ)言才能在該計(jì)算機(jī)上運(yùn)行,得到所需要的結(jié)果。但匯編語(yǔ)言的實(shí)踐啟發(fā)人們,表達(dá)成機(jī)器語(yǔ)言不必一步到位,可以分兩步走或者可以筑橋過(guò)河。即先表達(dá)成一種中介語(yǔ)言,然后轉(zhuǎn)成機(jī)器語(yǔ)言。匯編語(yǔ)言作為一種中介語(yǔ)言,并沒(méi)有獲得很大成功,原因是它離算法語(yǔ)
?
言還太遠(yuǎn)。這便指引人們?nèi)ピO(shè)計(jì)一種盡量接近算法語(yǔ)言的規(guī)范語(yǔ)言,即所謂的高級(jí)語(yǔ)言,讓程序員可以用它方便地表達(dá)算法,然后借助于規(guī)范的高級(jí)語(yǔ)言到規(guī)范的機(jī)器語(yǔ)言的"翻譯",最終將算法表達(dá)為機(jī)器語(yǔ)言。而且,由于高級(jí)語(yǔ)言和機(jī)器語(yǔ)言都具有規(guī)范性,這里的"翻譯"完全可以機(jī)械化地由計(jì)算機(jī)來(lái)完成,就像匯編語(yǔ)言被翻譯成機(jī)器語(yǔ)言一樣,只要計(jì)算機(jī)配上一個(gè)編譯程序。 上述兩步,前一步由程序員去完成,后一步可以由編譯程序去完成。在規(guī)定清楚它們各自該做什么之后,這兩步是完全獨(dú)立的。它們各自該如何做互不相干。前一步要做的只是用高級(jí)語(yǔ)言正確地表達(dá)給定的算法,產(chǎn)生一個(gè)高級(jí)語(yǔ)言程序;后一步要做的只是將第一步得到的高級(jí)語(yǔ)言程序翻譯成機(jī)器語(yǔ)言程序。至于程序員如何用高級(jí)語(yǔ)言表達(dá)算法和編譯程序如何將高級(jí)語(yǔ)言表達(dá)的算法翻譯成機(jī)器語(yǔ)言表達(dá)的算法,顯然毫不相干。
?
處理從算法語(yǔ)言最終表達(dá)成機(jī)器語(yǔ)言這一復(fù)雜過(guò)程的上述思想方法就是一種抽象。匯編語(yǔ)言和高級(jí)語(yǔ)言的出現(xiàn)都是這種抽象的范例。 與匯編語(yǔ)言相比,高級(jí)語(yǔ)言的巨大成功在于它在數(shù)據(jù)、運(yùn)算和控制三方
?
面的表達(dá)中引入許多接近算法語(yǔ)言的概念和工具,大大地提高抽象地表達(dá)算法的能力。 在運(yùn)算方面,高級(jí)語(yǔ)言如Pascal,除允許原封不動(dòng)地運(yùn)用算法語(yǔ)言的四則運(yùn)算、邏輯運(yùn)算、關(guān)系運(yùn)算、算術(shù)表達(dá)式、邏輯表達(dá)式外,還引入強(qiáng)有力的函數(shù)與過(guò)程的工具,并讓用戶自定義。這一工具的重要性不僅在于它精簡(jiǎn)了重復(fù)的程序文本段,而且在于它反映出程序的兩級(jí)抽象。
?
在函數(shù)與過(guò)程調(diào)用級(jí),人們只關(guān)心它能做什么,不必關(guān)心它如何做。只是到函數(shù)與過(guò)程的定義時(shí),人們才給出如何做的細(xì)節(jié)。用過(guò)高級(jí)語(yǔ)言的讀者都知道,一旦函數(shù)與過(guò)程的名稱、參數(shù)和功能被規(guī)定清楚,那么,在程序中調(diào)用它們便與在程序的頭部說(shuō)明它們完全分開。你可以修改甚至更換函數(shù)體與過(guò)程體,而不影響它們的被調(diào)用。如果把函數(shù)與過(guò)程名看成是運(yùn)算名,把參數(shù)看成是運(yùn)算的對(duì)象或運(yùn)算的結(jié)果,那么
?
,函數(shù)與過(guò)程的調(diào)用和初等運(yùn)算的引用沒(méi)有兩樣。利用函數(shù)和過(guò)程以及它們的復(fù)合或嵌套可以很自然地表達(dá)算法語(yǔ)言中任何復(fù)雜的運(yùn)算。
?
在數(shù)據(jù)方面,高級(jí)語(yǔ)言如Pascal引人了數(shù)據(jù)類型的概念,即把所有的數(shù)據(jù)加以分類。每一個(gè)數(shù)據(jù)(包括表達(dá)式)或每一個(gè)數(shù)據(jù)變量都屬于其中確定的一類。稱這一類數(shù)據(jù)為一個(gè)數(shù)據(jù)類型。 因此,數(shù)據(jù)類型是數(shù)據(jù)或數(shù)據(jù)變量類屬的說(shuō)明,它指示該數(shù)據(jù)或數(shù)據(jù)變量可能取的值的全體。對(duì)于無(wú)結(jié)構(gòu)的數(shù)據(jù),高級(jí)語(yǔ)言如Pascal,除提供標(biāo)準(zhǔn)的基本數(shù)據(jù)類型布爾型、字符型、整型和實(shí)型外,還提供用戶可自定義的枚舉類、子界類型和指針類型。這些類型(除指針外),其使用方式都順應(yīng)人們?cè)谒惴ㄕZ(yǔ)言中使用的習(xí)慣。對(duì)于有結(jié)構(gòu)的數(shù)據(jù),高級(jí)語(yǔ)言如Pascal,提供了數(shù)組、記錄、有限制的集合和文件等四種標(biāo)準(zhǔn)的結(jié)構(gòu)數(shù)據(jù)類型。其中,數(shù)組是科學(xué)計(jì)算中的向量、矩陣的抽象;記錄是商業(yè)和管理中的記錄的抽象;有限制的集合是數(shù)學(xué)中足夠小的集合的勢(shì)集的抽象;文件是諸如磁盤等外存儲(chǔ)數(shù)據(jù)的抽象。
?
人們可以利用所提供的基本數(shù)據(jù)類型(包括標(biāo)準(zhǔn)的和自定義的),按數(shù)組、記錄、有限制的集合和文件的構(gòu)造規(guī)則構(gòu)造有結(jié)構(gòu)的數(shù)據(jù)。 此外,還允許用戶利用標(biāo)準(zhǔn)的結(jié)構(gòu)數(shù)據(jù)類型,通過(guò)復(fù)合或嵌套構(gòu)造更復(fù)雜更高層的結(jié)構(gòu)數(shù)據(jù)。這使得高級(jí)語(yǔ)言中的數(shù)據(jù)類型呈明顯的分層。 高級(jí)語(yǔ)言中數(shù)據(jù)類型的分層是沒(méi)有窮盡的,因而用它們可以表達(dá)算法語(yǔ)言中任何復(fù)雜層次的數(shù)據(jù)。 在控制方面,高級(jí)語(yǔ)言如Pascal,提供了表達(dá)算法控制轉(zhuǎn)移的六種方式。
?
(1)缺省的順序控制";"。
?
(2)條件(分支)控制:"if表達(dá)式(為真)then S1 else S2;" 。
?
(3)選擇(情況)控制:
?
"Case 表達(dá)式 of
?
值1: S1
值2: S2
...
值n: Sn
end"
?
(4)循環(huán)控制:
?
"while 表達(dá)式(為真) do S;" 或
"repeat S until 表達(dá)式(為真);" 或
"for變量名:=初值 to/downto 終值do S;"
?
(5)函數(shù)和過(guò)程的調(diào)用,包括遞歸函數(shù)和遞歸過(guò)程的調(diào)用。
?
(6)無(wú)條件轉(zhuǎn)移goto。
這六種表達(dá)方式不僅覆蓋了算法語(yǔ)言中所有控制表達(dá)的要求,而且不再像機(jī)器語(yǔ)言或匯編語(yǔ)言那樣原始、那樣繁瑣、那樣隱晦,而是如上面所看到的,與自然語(yǔ)言的表達(dá)相差無(wú)幾。 程序設(shè)計(jì)語(yǔ)言從機(jī)器語(yǔ)言到高級(jí)語(yǔ)言的抽象,帶來(lái)的主要好處是: 高級(jí)語(yǔ)言接近算法語(yǔ)言,易學(xué)、易掌握,一般工程技術(shù)人員只要幾周時(shí)間的培訓(xùn)就可以勝任程序員的工作;高級(jí)語(yǔ)言為程序員提供了結(jié)構(gòu)化程序設(shè)計(jì)的環(huán)境和工具,使得設(shè)計(jì)出來(lái)的程序可讀性好,可維護(hù)性強(qiáng),可靠性高;高級(jí)語(yǔ)言遠(yuǎn)離機(jī)器語(yǔ)言,與具體的計(jì)算機(jī)硬件關(guān)系不大,因而所寫出來(lái)的程序可移植性好,重用率高; 由于把繁雜瑣碎的事務(wù)交給了編譯程序去做,所以自動(dòng)化程度高,開發(fā)周期短,且程、序員得到解脫,可以集中時(shí)間和精力去從事對(duì)于他們來(lái)說(shuō)更為重要的創(chuàng)造性勞動(dòng),以提高、程序的質(zhì)量。
?
數(shù)據(jù)結(jié)構(gòu)、數(shù)據(jù)類型和抽象數(shù)據(jù)類型
?
數(shù)據(jù)結(jié)構(gòu)、數(shù)據(jù)類型和抽象數(shù)據(jù)類型,這三個(gè)術(shù)語(yǔ)在字面上既不同又相近,反映出它們?cè)诤x上既有區(qū)別又有聯(lián)系。
?
數(shù)據(jù)結(jié)構(gòu)是在整個(gè)計(jì)算機(jī)科學(xué)與技術(shù)領(lǐng)域上廣泛被使用的術(shù)語(yǔ)。它用來(lái)反映一個(gè)數(shù)據(jù)的內(nèi)部構(gòu)成,即一個(gè)數(shù)據(jù)由哪些成分?jǐn)?shù)據(jù)構(gòu)成,以什么方式構(gòu)成,呈什么結(jié)構(gòu)。數(shù)據(jù)結(jié)構(gòu)有邏輯上的數(shù)據(jù)結(jié)構(gòu)和物理上的數(shù)據(jù)結(jié)構(gòu)之分。邏輯上的數(shù)據(jù)結(jié)構(gòu)反映成分?jǐn)?shù)據(jù)之間的邏輯關(guān)系,物理上的數(shù)據(jù)結(jié)構(gòu)反映成分?jǐn)?shù)據(jù)在計(jì)算機(jī)內(nèi)的存儲(chǔ)安排。數(shù)據(jù)結(jié)構(gòu)是數(shù)據(jù)存在的形式。
?
數(shù)據(jù)是按照數(shù)據(jù)結(jié)構(gòu)分類的,具有相同數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)屬同一類。同一類數(shù)據(jù)的全體稱為一個(gè)數(shù)據(jù)類型。在程序設(shè)計(jì)高級(jí)語(yǔ)言中,數(shù)據(jù)類型用來(lái)說(shuō)明一個(gè)數(shù)據(jù)在數(shù)據(jù)分類中的歸屬。它是數(shù)據(jù)的一種屬性。這個(gè)屬性限定了該數(shù)據(jù)的變化范圍。為了解題的需要,根據(jù)數(shù)據(jù)結(jié)構(gòu)的種類,高級(jí)語(yǔ)言定義了一系列的數(shù)據(jù)類型。不同的高級(jí)語(yǔ)言所定義的數(shù)據(jù)類型不盡相同。Pascal語(yǔ)言所定義的數(shù)據(jù)類型的種類。
?
其中,簡(jiǎn)單數(shù)據(jù)類型對(duì)應(yīng)于簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu);構(gòu)造數(shù)據(jù)類型對(duì)應(yīng)于復(fù)雜的數(shù)據(jù)結(jié)構(gòu);在復(fù)雜的數(shù)據(jù)結(jié)構(gòu)里,允許成分?jǐn)?shù)據(jù)本身具有復(fù)雜的數(shù)據(jù)結(jié)構(gòu),因而,構(gòu)造數(shù)據(jù)類型允許復(fù)合嵌套;指針類型對(duì)應(yīng)于數(shù)據(jù)結(jié)構(gòu)中成分?jǐn)?shù)據(jù)之間的關(guān)系,表面上屬簡(jiǎn)單數(shù)據(jù)類型,實(shí)際上都指向復(fù)雜的成分?jǐn)?shù)據(jù)即構(gòu)造數(shù)據(jù)類型中的數(shù)據(jù),因此這里沒(méi)有把它劃入簡(jiǎn)單數(shù)據(jù)類型,也沒(méi)有劃入構(gòu)造數(shù)據(jù)類型,而單獨(dú)劃出一類。
?
數(shù)據(jù)結(jié)構(gòu)反映數(shù)據(jù)內(nèi)部的構(gòu)成方式,它常常用一個(gè)結(jié)構(gòu)圖來(lái)描述:數(shù)據(jù)中的每一項(xiàng)成分?jǐn)?shù)據(jù)被看作一個(gè)結(jié)點(diǎn),并用方框或圓圈表示,成分?jǐn)?shù)據(jù)之間的關(guān)系用相應(yīng)的結(jié)點(diǎn)之間帶箭號(hào)的連線表示。如果成分?jǐn)?shù)據(jù)本身又有它自身的結(jié)構(gòu),則結(jié)構(gòu)出現(xiàn)嵌套。這里嵌套還允許是遞歸的嵌套。
?
由于指針數(shù)據(jù)的引入,使構(gòu)造各種復(fù)雜的數(shù)據(jù)結(jié)構(gòu)成為可能。按數(shù)據(jù)結(jié)構(gòu)中的成分?jǐn)?shù)據(jù)之間的關(guān)系,數(shù)據(jù)結(jié)構(gòu)有線性與非線性之分。在非線性數(shù)據(jù)結(jié)構(gòu)中又有層次與網(wǎng)狀之分。 由于數(shù)據(jù)類型是按照數(shù)據(jù)結(jié)構(gòu)劃分的,因此,一類數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)著一種數(shù)據(jù)類型。數(shù)據(jù)類型按照該類型中的數(shù)據(jù)所呈現(xiàn)的結(jié)構(gòu)也有線性與非線性之分,層次與網(wǎng)狀之分。一個(gè)數(shù)據(jù)變量,在高級(jí)語(yǔ)言中的類型說(shuō)明必須是讀變量所具有的數(shù)據(jù)結(jié)構(gòu)所對(duì)應(yīng)的數(shù)據(jù)類型。最常用的數(shù)據(jù)結(jié)構(gòu)是數(shù)組結(jié)構(gòu)和記錄結(jié)構(gòu)。數(shù)組結(jié)構(gòu)的特點(diǎn)是:
?
成分?jǐn)?shù)據(jù)的個(gè)數(shù)固定,它們之間的邏輯關(guān)系由成分?jǐn)?shù)據(jù)的序號(hào)(或叫數(shù)組的下標(biāo))來(lái)體現(xiàn)。這些成分?jǐn)?shù)據(jù)按照序號(hào)的先后順序一個(gè)挨一個(gè)地排列起來(lái)。每一個(gè)成分?jǐn)?shù)據(jù)具有相同的結(jié)構(gòu)(可以是簡(jiǎn)單結(jié)構(gòu),也可以是復(fù)雜結(jié)構(gòu)),因而屬于同一個(gè)數(shù)據(jù)類型(相應(yīng)地是簡(jiǎn)單數(shù)據(jù)類型或構(gòu)造數(shù)據(jù)類型)。這種同一的數(shù)據(jù)類型稱為基類型。所有的成分?jǐn)?shù)據(jù)被依序安排在一片連續(xù)的存儲(chǔ)單元中。 概括起來(lái),數(shù)組結(jié)構(gòu)是一個(gè)線性的、均勻的、其成分?jǐn)?shù)據(jù)可隨機(jī)訪問(wèn)的結(jié)構(gòu)。
?
由于這、種結(jié)構(gòu)有這些良好的特性,所以最常被人們所采用。在高級(jí)語(yǔ)言中,與數(shù)組結(jié)構(gòu)相對(duì)應(yīng)的、數(shù)據(jù)類型是數(shù)組類型,即數(shù)組結(jié)構(gòu)的數(shù)據(jù)變量必須說(shuō)明為array [i] of T0 ,其中i是數(shù)組、結(jié)構(gòu)的下標(biāo)類型,而T0是數(shù)組結(jié)構(gòu)的基類型。 記錄結(jié)構(gòu)是另一種常用的數(shù)據(jù)結(jié)構(gòu)。它的特點(diǎn)是:與數(shù)組結(jié)構(gòu)一樣,成分?jǐn)?shù)據(jù)的個(gè)數(shù)固定。但成分?jǐn)?shù)據(jù)之間沒(méi)有自然序,它們處于平等地位。每一個(gè)成分?jǐn)?shù)據(jù)被稱為一個(gè)域并賦予域名。不同的域有不同的域名。不同的域允許有不同的結(jié)構(gòu),因而允許屬于不同的數(shù)據(jù)類型。與數(shù)組結(jié)構(gòu)一樣,它們可以隨機(jī)訪問(wèn),但訪問(wèn)的途徑靠的是域名。在高級(jí)語(yǔ)言中記錄結(jié)構(gòu)對(duì)應(yīng)的數(shù)據(jù)類型是記錄類型。記錄結(jié)構(gòu)的數(shù)據(jù)的變量必須說(shuō)明為記錄類型。
?
抽象數(shù)據(jù)類型的含義在上一段已作了專門敘述。它可理解為數(shù)據(jù)類型的進(jìn)一步抽象。即把數(shù)據(jù)類型和數(shù)據(jù)類型上的運(yùn)算捆在一起,進(jìn)行封裝。引入抽象數(shù)據(jù)類型的目的是把數(shù)據(jù)類型的表示和數(shù)據(jù)類型上運(yùn)算的實(shí)現(xiàn)與這些數(shù)據(jù)類型和運(yùn)算在程序中的引用隔開,使它們相互獨(dú)立。對(duì)于抽象數(shù)據(jù)類型的描述,除了必須描述它的數(shù)據(jù)結(jié)構(gòu)外,還必須描述定義在它上面的運(yùn)算(過(guò)程或函數(shù))。抽象數(shù)據(jù)類型上定義的過(guò)程和函
數(shù)以該抽象數(shù)據(jù)類型的數(shù)據(jù)所應(yīng)具有的數(shù)據(jù)結(jié)構(gòu)為基礎(chǔ)。
?
泛型設(shè)計(jì)和數(shù)據(jù)結(jié)構(gòu)與算法
?
下面我想再說(shuō)說(shuō)關(guān)于泛型程序設(shè)計(jì)模型對(duì)于數(shù)據(jù)結(jié)構(gòu)和算法方面的最新推動(dòng),泛型思想已經(jīng)把數(shù)據(jù)結(jié)
?
構(gòu)和算法方面的基本思想抽象到了一個(gè)前所未有的高度,現(xiàn)在有多種程序設(shè)計(jì)語(yǔ)言支持泛型設(shè)計(jì),比如
ADA,C++,而且據(jù)說(shuō)在JAVA的下一版本和C#中也將對(duì)泛型設(shè)計(jì)進(jìn)行全面的支持。
?
先說(shuō)說(shuō)泛型設(shè)計(jì)的基本思想:泛型編程(generic programming,以下直接以GP稱呼)是一種全新的程序設(shè)計(jì)思想,和OO,OB,PO這些為人所熟知的程序設(shè)計(jì)想法不同的是GP抽象度更高,基于GP設(shè)計(jì)的組件之間偶合度底,沒(méi)有繼承關(guān)系,所以其組件間的互交性和擴(kuò)展性都非常高。我們都知道,任何算法都是作用在一種特定的數(shù)據(jù)結(jié)構(gòu)上的,最簡(jiǎn)單的例子就是快速排序算法最根本的實(shí)現(xiàn)條件就是所排序的對(duì)象是存
貯在數(shù)組里面,因?yàn)榭焖倥判蚓褪且驗(yàn)橐玫綌?shù)組的隨機(jī)存儲(chǔ)特性,即可以在單位時(shí)間內(nèi)交換遠(yuǎn)距離的對(duì)象,而不只是相臨的兩個(gè)對(duì)象,而如果用聯(lián)表去存儲(chǔ)對(duì)象,由于在聯(lián)表中取得對(duì)象的時(shí)間是線性的既O[n],這樣將使快速排序失去其快速的特點(diǎn)。也就是說(shuō),我們?cè)谠O(shè)計(jì)一種算法的時(shí)候,我們總是先要考慮其應(yīng)用的數(shù)據(jù)結(jié)構(gòu),比如數(shù)組查找,聯(lián)表查找,樹查找,圖查找其核心都是查找,但因?yàn)樽饔玫臄?shù)據(jù)結(jié)構(gòu)不同
?
將有多種不同的表現(xiàn)形式。數(shù)據(jù)結(jié)構(gòu)和算法之間這樣密切的關(guān)系一直是我們以前的認(rèn)識(shí)。泛型設(shè)計(jì)的根本思想就是想把算法和其作用的數(shù)據(jù)結(jié)構(gòu)分離,也就是說(shuō),我們?cè)O(shè)計(jì)算法的時(shí)候并不去考慮我們?cè)O(shè)計(jì)的算法將作用于何種數(shù)據(jù)結(jié)構(gòu)之上。泛型設(shè)計(jì)的理想狀態(tài)是一個(gè)查找算法將可以作用于數(shù)組,聯(lián)表,樹,圖等各種數(shù)據(jù)結(jié)構(gòu)之上,變成一個(gè)通用的,泛型的算法。這樣的理想是不是很誘惑人?
?
泛型編程帶來(lái)的是前所未有的彈性以及不會(huì)損失效率的抽象性,GP和OO不同,它不要求你通過(guò)額外的間接層來(lái)調(diào)用函數(shù):它讓你撰寫完全一般化并可重復(fù)使用的算法,其效率與針對(duì)特定數(shù)據(jù)結(jié)構(gòu)而設(shè)計(jì)的算法旗鼓相當(dāng)。我們大家都知道數(shù)據(jù)結(jié)構(gòu)在C++中可以用用戶定義類型來(lái)表示,而C++中的模板技術(shù)就是以類型作為參數(shù),那么我可以想象利用模板技術(shù)可以實(shí)現(xiàn)我們開始的GP思想,即一個(gè)模板函數(shù)可以對(duì)于各種傳遞進(jìn)來(lái)的類型起作用,而這些類型就可以是我們定義的各種數(shù)據(jù)結(jié)構(gòu)。
?
泛型算法抽離于特定類型和特定數(shù)據(jù)結(jié)構(gòu)之外,使得其適應(yīng)與盡可能的一般化類型,算法本身只是為了實(shí)現(xiàn)算法其需要表達(dá)的邏輯本質(zhì)而不去被為各種數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)細(xì)節(jié)所干擾。這意味著一個(gè)泛型算法實(shí)際具有兩部分。1,用來(lái)描敘算法本質(zhì)邏輯的實(shí)際指令;2,正確指定其參數(shù)類型必須滿足的性質(zhì)的一組需求條件。到此,相信有不少人已經(jīng)開始糊涂了,呵呵,不要緊。畢竟GP是一種抽象度非常高的程序設(shè)計(jì)思想,里面的核心就是抽象條件成為成為程序設(shè)計(jì)過(guò)程中的核心,從而取代了類型這在OO里面的核心地位,正是因?yàn)轭愋筒辉谑俏覀兛紤]的重點(diǎn),類型成為了抽象條件的外衣,所以我們稱這樣的程序思想為泛型思想把類型泛化。 堆疊大陸合成表2022最新一覽 一、建筑配方1、房子:2木頭+1石頭2、伐木場(chǎng):3木頭+1石頭燃野3、采石場(chǎng):1木頭+3石頭4、花園:2木頭+2石頭5、農(nóng)場(chǎng):2木板+2磚塊+1泥土6、礦場(chǎng):2燧石+1石頭+1木頭7、熔爐:2燧石+2磚塊+1木板8、貨棚:1木頭+1石頭+1樹枝9、倉(cāng)庫(kù):1鐵錠+1石頭10、磚窯:1磚+1木頭坦畢+1鐵錠11、鋸木廠:1鐵錠+1木頭+1木板+1石頭12、篝火:1樹枝+1燧石13、畜棚:2木板+2木頭+1鐵錠14、爐子:1石磚+1鐵錠+1燧石15、市場(chǎng):1石磚+1木板+3金幣16、神廟:5石磚+5木板+3鐵錠(3居民(圣杯召喚))二、物品配方17、長(zhǎng)矛:1木頭+兩樹枝18、劍:1鐵+2樹枝19、狗:狼+骨頭20、水果沙拉:樹莓+蘋果21、蛋卷:2雞蛋讓段芹22、奶昔:1草莓+1牛奶23、雞蛋餅:1土豆+1雞蛋24、燉湯:1肉+1土豆+1洋蔥+1胡蘿卜 內(nèi)核模式硬件強(qiáng)制堆棧保護(hù)開不開 內(nèi)核模式硬件強(qiáng)制堆棧保護(hù)是一種操作系統(tǒng)的安全性特性。開啟該特性可以使得操作系統(tǒng)在內(nèi)核態(tài)下對(duì)堆棧的使用進(jìn)行限制,防止惡意軟件利用堆棧溢出漏洞進(jìn)行攻擊。
堆棧溢出漏洞是指在程序運(yùn)行過(guò)程中,當(dāng)程序向堆棧中寫入過(guò)多的數(shù)據(jù)時(shí),會(huì)導(dǎo)致數(shù)據(jù)溢出到其他內(nèi)存區(qū)域中,從而產(chǎn)生安全漏洞。攻擊者可以利用這種漏洞來(lái)修改程序的執(zhí)行流程,從而實(shí)現(xiàn)攻擊目的。
因此,在操作系統(tǒng)內(nèi)核態(tài)下開啟內(nèi)核模式硬件強(qiáng)制堆棧保護(hù)可以有效地防止堆棧溢出漏洞對(duì)系統(tǒng)的影響。當(dāng)然,該特性也會(huì)對(duì)系統(tǒng)的性能產(chǎn)生一定程度的影響。
在實(shí)際應(yīng)用中,我們需要根據(jù)具體情況來(lái)決定是否開啟內(nèi)核模式硬件強(qiáng)制堆棧保護(hù)。如果系統(tǒng)對(duì)安全性要求較高,建議開啟該特性。如果系統(tǒng)對(duì)性能有較高的要求,可以考慮關(guān)閉該特性來(lái)提高系統(tǒng)的運(yùn)行效率。