引言算法
我想經過這個教程,使得讀者不須要寫太多代碼,便能理解數據結構的概念和重要性。
編程
不少算法是運行在特殊的數據結構之上的,能夠說數據結構和算法是相輔相成的,有句出自某書的很是經典的話是這樣說的:數組
Algorithms Plus Data Structures Equals Programs數據結構
即算法加數據結構等於程序。注意這裏是程序,不是軟件。軟件還有工程性在其中。數據結構和算法
可是我依然但願可以不講太多的算法,由於「算法」太多,經過學習大量算法來學習數據結構的方式有些捨本逐末。函數
我會盡可能從構造和設計的角度來闡述數據結構。學習
構造即咱們手上有什麼,怎麼利用這些去製造咱們須要的結構。spa
設計即咱們的目的是什麼,爲了達成這個目的咱們須要什麼結構。設計
在內存裏存儲數據指針
在C語言中,咱們要處理的數據,都存儲在內存中,即使是硬盤中某個文件裏存放的小說,要對其內容進行處理,咱們依然須要將其加載到內存中,再接着進行後續的處理。
當咱們在C語言裏定義一個變量,諸如:
int o;
在這句代碼以後,咱們即可以操做這個變量。
咱們能夠往裏面存放一個整數,那這個整數有多大呢?使用
printf("%d",sizeof(int));
這句代碼,能夠輸出int型變量在其運行設備上的大小。若是你在你的筆記本電腦上編譯運行,這個大小應該是4,即4bytes,換算成二進制位(bit)即4*8=32bits。
咱們能夠利用sizeof測出全部基本類型的大小。這樣就有不少不一樣的盒子去放數據了。
內存裏的數據看起來怎麼樣
上面咱們建立了一個int型變量o。在內存裏看起來是這樣的:
固然如今什麼都沒有,由於在定義的時候並未初始化,咱們也沒聽任何東西進去。如今存點東西進去:
o = 11;
這下變成這樣了:
最後咱們顯示出這個數據存儲單元在內存中的位置(變量地址):
printf("%d",&o);
如今咱們什麼都有了:
移動數據
先看看這樣一個程序:
#include <stdio.h> void showcopies(int copies) { printf("copies %d\n",&copies); } int main(void) { int o; o = 11; printf("original %d\n",&o); showcopies(o); return 0; }
在這個程序裏咱們定義了一個函數,而且利用參數傳遞,將變量o「移動」到了showcopies這個函數中,而且「更名」叫作copies。
主函數main裏輸出了o這個變量的地址,showcopies裏輸出了移動後的o的地址。
最後的結果是什麼樣呢?能夠試着運行看看。
我去泡杯咖啡喝……
若是你在程序里加入了輸出變量o和變量copies的值的語句,你會更加確定,被「移動」的只有變量o的值而已。
也就是說,當咱們進行參數傳遞的時候,實際上是在新的一塊內存區域裏開闢一個一樣大小的空間,而後把做爲參數傳遞的變量的內存空間裏的數據複製到新的空間中。
一組數據
數組(Array)這個名字其實有些呆,由於光看中文名給人的感受就是一組數,諸如(1,2,3)這樣的,但事實上還能夠是('a','b','c')。我傾向於把Array理解爲一列數據或者一組數據。
#include <stdio.h> int main(void) { int m[3]; int i; for(i=0;i<3;i++) printf("%d\n",&m[i]); return 0; }
運行上面的程序,就能夠看到(圖畫的我累,因此這裏不畫了=。=)這樣的結果:
2686736
2686740
2686744
這三個地址即是數組m裏三個依次相鄰元素的地址。由於每一個int變量佔據4bytes,因此這三個int變量的地址是依次相差4(bytes)。數據裏的數據,在內存裏是連續存放的。
這樣的好處在於訪問會特別快,咱們只須要知道第一個變量的地址,就能經過向後移動必定的位置來讀取另外一個變量。
正如咱們在程序裏使用的訪問方式同樣,[]括號里加入索引號,便能訪問,在實際的程序運行中,這種直接訪問的速度也很是快。
移動一組數據或自定義數據類型
當咱們嘗試在函數調用的時候傳遞數組(Array)或者自定義的數據類型(結構體)時,會出現一種例外。
由於這兩類數據在內存裏佔用的空間可能會很大,因此所有複製到一個新空間裏實在不是很划算的一件事。甚至多數時候咱們不須要一個新的備份,只須要在原來的數據上修改就行。
因此對於這兩類數據,C語言裏使用指針(Pointer)來操做。
int m[3]; int *first_element_address; first_element_address = &m[0];
printf("%d\n",*(first_element_address+1)==m[1]);
當調用函數時,會生成傳遞參數的指針變量,再將這個指針變量傳遞過去。
至於驗證方法,能夠利用移動數據一段中的程序來檢驗。做業1。
/* Cheatsheet for using pointer in C */ /* 生成指針 */ pointer = &variable; /* 用指針讀取指向變量的值,再與指向變量的值進行相等判斷 */ *pointer == variable; /* 當pointer指向一塊連續數據區域時,例如數組 */ *(pointer+index) == array[index];
來,咱們來實現一個可變數組
先看看C語言的數組,有兩個明細的缺陷:
若是訪問數組的時候下標(索引值)越界,會發生錯誤。
數組的大小是固定的。
所以咱們要設計一個用起來更好的,好比擁有以下特性:
能夠檢查是否越界
可變大小
數組的數據在內存中皆是連續存放的,所以咱們須要一個用於存放連續數據的區域。
做業2
參考
http://en.wikipedia.org/wiki/Algorithms_%2B_Data_Structures_%3D_Programs
《Linux C編程一站式學習》 宋勁杉