資料結構筆記整理和思考--零碎(1)

eBusinessMan發表於2015-03-15

1.      資料結構主要是研究現實中大而複雜的問題如何以特定的資料型別和特定的儲存結構儲存在主儲存器(記憶體)中(簡而言之,在記憶體中,個體的如何儲存和個體之間關係如何儲存)。而如何對這些資料進行操作,就叫做演算法。

2.      陣列:由於是連續儲存,故往往要開闢新的記憶體以保證連續,那麼對已有空閒記憶體的利用率很低。

線性表:離散儲存,可以將記憶體的間隙(或者說記憶體碎片)都利用起來。可是在實際使用的過程中,例如開發人事管理系統時,線性表表現不了“上級和下級”關係。

樹:可以表現現實中有階級關係的問題,如公司人事管理系統

圖:一般在交通規劃中使用,如怎樣保證任意兩個站點距離市中心的距離一致,再如百度地圖中,計算任意兩個點之間的距離等。

3.      衡量演算法的標準:時間複雜度(最關鍵的步驟的執行次數),空間複雜度,難易程度,健壯性(即:能處理輸入的惡意非法資料,不會報錯生病)。

4.      棧記憶體和堆記憶體的區別是:記憶體的分配方式的不同(前者是通過出棧壓棧的方式分配),而不是兩個記憶體區域。

5.      CPU 直接可以操作的最大儲存空間是記憶體。記憶體,可以形象地劃分為一個個的小格子,每一個格子都有唯一的編號(0 —— 4G-1),這就是地址,也就是指標。也就是說指標就是一個記憶體單元地址,或者說 一個操作有限(加減乘除有限)的非負整數。而指標標量則是存放指標的變數。

6.      儲存單元一般應具有儲存資料和讀寫資料的功能,以8位二進位制作為一個儲存單元,也就是一個位元組。每個單元有一個地址,是一個整數編碼,可以表示為二進位制整數。程式中的變數和主儲存器的儲存單元相對應:變數的名字對應著儲存單元的地址,變數內容對應著單元所儲存的資料。儲存地址一般用十六進位制數表示,而每一個儲存器地址中又存放著一組二進位制(或十六進位制)表示的數,通常稱為該地址的內容。

7.      C語言指標辨析:

操作一個變數,就是間接地操作這個變數存放的內容

int  i = 10;

i ++;                //i存放的內容加1

Int  j=i;  //i存放的內容賦給j;

 

*P : 代表 指標變數p所存放的內容

int  * p ;  (p 是指標變數名,也是一個變數,對應著一個記憶體單元地址,但存放的內容是地址)

int  * q;   (p)

int   i=10;  (i 是變數名,對應著一個記憶體單元地址,也就是說,i是一個地址(或指標),存放的內容是整形資料)

int   j;       (j i)

 

p = &i(將變數i的地址 賦給 p  , 那麼p的內容*p就是i對應的記憶體單元地址,這樣 *p  就等價於 i ,  可以直接將*p看成i來用)

j = *p;   (由上面,*p 可以看成 i  ,  在此就是 j = i)

q = p;   (p 存放的地址 賦給 指標變數,這樣的話,*q 就是 &i ,那麼*q 就是i )

8.      一維陣列 int[] arr = {1,2,3,4}

a)       一維陣列名arr 是一個指標常量,存放的是arr[0]的地址(不是內容),存放的是不能修改的。

b)       由於陣列的實體地址是連續的,所以arr[3] == *(a+3)

問題:常量 和 變數 在記憶體中的區別是什麼?

9.    有人說,java中沒有指標的概念,這的確是,因為java程式設計中我們的確無法像C語言這樣獲取到一個變數的地址;可是java中卻有C語言中的指標變數的概念,就是物件或陣列的引用!!  
但是C中的指標要比java的物件引用變數靈活的多,例如java中一個變數我們無法獲取其地址,只能獲取其內容,然而,C中,通過 &變數名  就可以獲取這個變數的地址。

10.   任何型別的指標變數都是佔用4個位元組。任何型別的指標變數都是隻存放著指標的第一個或最後一個位元組而已。

11.    C語言中,對於一個結構體struct Student st{int id,String name,int money},函式f(struct Student * pst)g(struct Student st),使用後面兩個函式來列印結構體的值時,後者會耗更多的記憶體和時間的,因為前者是將結構體st的記憶體地址傳送給形參,而後者則是將st的內容傳送給形參,很明顯後者得傳送很大的資料。這是C語言中一些記憶體優化細節方面的現象了。

對比java中的類作為引數傳遞:假設有class Student{ int id;String name;int money }和函式f(Student st),有一下常見的程式設計習慣:

1, fnew Student());

2, Student st = new Student();

fst;

         這兩種方式就沒有C語言中的那麼複雜,因為new Student() 返回的就只是開闢的記憶體空間的首地址,不會是這個物件的內容,所以這兩種方式不會像上面的C語言的例子中的“傳遞地址”和“傳遞內容”的區別。

 

12.    malloc(int a) :返回型別是 void* 型別。void* 表示未確定型別的指標。C,C++規定,void* 型別可以強制轉換為任何其它型別的指標。即,動態開闢a個位元組的記憶體空間,然後將第一個位元組的地址返回。注意的是,這個新的記憶體空間是不屬於任何型別的,所以我們可以自己將其強制轉化成某種資料型別的記憶體空間,例如

a)     int * p = (int *) malloc(int a);// 整型儲存單元,並將這128個連續的整型儲存單元的首地址儲存到指標變數p中,所以其實是int陣列。

b)    String * p = (String *) malloc(int a); //其實是String陣列

//////////反思javanew//////////

Java中我們經常使用new來開闢堆記憶體,其實底層實現是:

         A a = new A();

à    A a = (A)malloc(sizeOf(A));

13.    陣列與指標的關係:我們知道int[] arr =new int[10] 是指在記憶體中開闢10*4個位元組的連續的整型儲存單元,然後將這個空間的第一個位元組的記憶體單元地址賦給指標arr (即arr = &arr[0] )。

int * parr = (int *)malloc(10*4);其實和上面的過程一樣。應該說陣列的底層實現就是後者。

14.   記憶體洩漏也稱作“儲存滲漏”,用動態儲存分配函式動態開闢的空間,在使用完畢後未釋放,結果導致一直佔據該記憶體單元。直到程式結束。其實說白了就是該記憶體空間使用完畢之後未回收.

15.    C語言中我們可以自己動態分配記憶體(malloc(int)),也可以自己釋放記憶體(free(指標變數)),可是在大型而複雜的專案之中,很多時候我們由於種種原因沒有free記憶體(例如忘了),這樣子的話,記憶體就會佔用得越來越多,所以系統就會越來越慢。一個例子就是我們的OS,其核心都是C語言寫的,當用得久的話,我們就會明顯感覺卡了。這也是為什麼我們說CC++語言不安全的原因容易記憶體洩露,而java由於獨特的GC機制,所以記憶體都自動回收了。從這個點來說,java的開發的系統又比C++開發的好了,至少沒那麼容易奔潰,哈哈。

16.    我們將現實世界中的業務資料存放進記憶體中時,往往有兩種方式:線性結構(陣列,連結串列等)和非線性結構(樹和圖)。

所謂線性結構:就是所有結點可以通過一條線串起來。

線性結構又分為兩類:連續儲存(陣列)和離散儲存(連結串列)

17.    typedef 資料型別 別名 -----&gt  常用於 為名字過長的結構體(指標變數) 取別名(一般用大寫)

typedef struct Student {

         int age; String name

}  STU;    àà  就是說為結構體Student  起一個別名 STU

typedef struct Student {

         int age; String name

} * PSTU;    àà  就是說為結構體Student的指標變數型別  起一個別名 PSTU


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29900383/viewspace-1460771/,如需轉載,請註明出處,否則將追究法律責任。

相關文章