寫給你的數據結構教程(第一天)

引言算法

我想經過這個教程,使得讀者不須要寫太多代碼,便能理解數據結構的概念和重要性。
編程

不少算法是運行在特殊的數據結構之上的,能夠說數據結構和算法是相輔相成的,有句出自某書的很是經典的話是這樣說的:數組

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語言的數組,有兩個明細的缺陷:

  1. 若是訪問數組的時候下標(索引值)越界,會發生錯誤。

  2. 數組的大小是固定的。

所以咱們要設計一個用起來更好的,好比擁有以下特性:

  1. 能夠檢查是否越界

  2. 可變大小

數組的數據在內存中皆是連續存放的,所以咱們須要一個用於存放連續數據的區域。

做業2


參考

  1. http://en.wikipedia.org/wiki/Algorithms_%2B_Data_Structures_%3D_Programs

  2. 《Linux C編程一站式學習》 宋勁杉

相關文章
相關標籤/搜索