咱們如何把現實中大量而複雜的問題,以特定的數據類型和特定的存儲結構保存到主存儲器(內存)中,以及在此基礎上爲實現某個功能(好比查找某個元素,刪除某個元素,對全部元素進行排序)而執行的相應操做。這個相應的操做也叫算法。java
數據結構 =個體的存儲 + 個體的關係存儲算法
算法(狹義) = 對存儲數據的操做數組
2.1.1.時間複雜度:程序大概執行的次數,而非執行的時間數據結構
2.1.2.空間複雜度:算法執行過程當中大概所佔用的最大內存ide
2.1.3.難易程度(編算法最重要的)函數
2.1.4.健壯性spa
程序 = 數據的存儲 + 數據的操做 + 能夠被計算機執行的語言操作系統
指針就是地址 地址就是指針,指針和地址是一個概念指針
指針變量 是存放內存單元地址的變量,所謂內存單元地址 即爲內存單元編號,二者是一個概念code
指針的本質 是一個操做受限的非負整數/從0開始的非負整數
範圍:0 -- FFFFFFFF【4G-1】
CPU可以直接訪問的只有內存,內存是CPU惟一可以訪問的大容量儲存器,內存的基本劃分單位是字節,每一個字節有8位,每一位存放1個0或1個1,CPU和內存打交道的方式:地址線、控制線、數據線
內存能夠看作不少小格子,若是是32位,編號從0到4G-1;
1.2.1.1.地址線 能夠肯定對哪個單元編號進行操做,地址沒有編號,地址就是編號;重點是地址線,由於地址線是32位的,因此最大隻能0到32-1;內存的編號不能重複,可是內容能夠重複;
定義:地址就是內存單元的編號,單元編號是死的,不能改變,可是裏面的內容是能夠改變的;當一個程序運行完成,內存會被回收(回收和銷燬不是一個概念,操做系統會分配內存給程序,程序告訴操做系統,操做系統會把內存中的空間釋放出來,原始的數據(遺留的垃圾數字)不會銷燬,只是不能使用而已(c存在這個問題,可是java不會,java會自動釋放),其中的變量會被清空,可是內存、單元編號依然存在;
1.2.1.2.控制線 用來肯定是:讀、寫、只讀、只寫;
1.2.1.3.數據線 能夠進行數據傳輸
1 #include <stdio.h> 2 3 int main(void) 4 { 5 int * p; //該p變量只能存儲int類型的地址,不能存放一個整數 6 int i = 10; 7 int j; 8 9 // char ch = 'A'; 10 // p = &ch; //p只能存放int類型,不能存放char類型的'A',類型不一致,會報錯 11 // p = 10; //error p是個變量名字,表示只能存放int型變量地址,10是個整數,不是個地址; 12 // *p = i; //能夠存放i,必定要以下理解才能夠 13 // 1)將i的地址發送給p,意味着p是指向i的; 14 // 2)修改p、i的值,不會影響另一個值,相互不會影響; 15 // 3)*p即爲i變量自己,i跟*p能夠在任何地方進行互換,i的值改了,*p的值也改了,i原來等於100,*p也就等於100,可是p不是i,i不是p; 16 p = &i; // 若是這一行被省略掉,會報錯; 17 // 第一步int * p;只是說p能夠保存整型變量地址了,但p中並無保存真正的整型變量地址,因此咱們不知道*p真正指向的是誰了 18 // 雖然p中沒有保存真正有效整型數字地址,可是p中仍是能夠有垃圾數字的,垃圾數字也有多是某一個變量的地址,因此*p最終指向的是一個不肯定的單元,*p不知道指向了哪裏,形成了混亂,c語言中不容許這樣去寫 19 // 不能將一個不肯定單元的值,賦給另一個變量,這樣不合適,因此會報錯 20 *p = i; // 等價於i=i,不會出錯,可是沒有什麼實際意義 21 j = *p; // 等價於j = i; 若註釋掉這一行,則j沒有賦值,c會自動賦予一個垃圾數字-2341343; 22 printf("i = %d, j= %d, *p = %d\n",i, j, *p); 23 24 //printf(); 25 return 0; 26 }
小結:
一、若是一個指針變量(假定爲p)存放了某個普通變量,那咱們就能夠說:「p指向了i」,但p與i是兩個變量;修改p的值不影響i的值,修改i的值不影響p的值
二、*p等價於I 或者說*p能夠與i在任何地方互換
三、若是一個指針變量指向了某個普通變量,則*指針變量就徹底等價於該普通變量
注意:
指針變量也是變量,只不過它存放的不能是內存單元的內容,只能存放內存單元的地址
普通變量前不能加*
常量和表達式前不能加&
如何經過被調函數,修改主調函數中普通變量的值
1.實參爲相關變量的地址:&i
2.形參爲以該變量的類型爲類型的指針變量:*p
3.在被調用函數中經過*形參變量名的方式修改主函數:*p=100
//Array_point_1.cpp # include <stdio.h> int main(void) { int a[5] = {1,2,3,4,5}; // 1)a中存放的不是1~5這5個數字,這5個數字是在a0到a4中存放的。 // 2)數組名a存放的是數組的第一個元素的地址 // 3)它的值不能被改變 // 4)字母a即爲一維數組名,指向的是數組的第一個元素,即a指向的是a0 // 5)a[3]和*(a+3)的關係:a[i] <<==>> *(a+i) 即數組a[i]的寫法,等價於*(a+i) a[3] == *(3+a), 3[a] == *(a+3), 因a指向第一個元素a[0],故a+3指向第四個元素a[3],則*(a+3)==a[3]; // 理論上指針比下標的速度快,可是能夠忽略不計 //a[3] == *(3+a); printf("%p\n", a+1); printf("%p\n", a+2); printf("%p\n", a+3); //[Out]: //0019FF30 //0019FF34 //0019FF38 printf("%d\n", *a+3); // *a+3等價於 a[0]+3 = 4 //[Out]: // 4 return 0; }
一維數組名 是個指針常量,它存放的是一維數組第一個元素的地址a[0],它的值不能被改變
一維數組名指向的是 數組的第一個元素
a[i] <<==>> *(a+i)
假設指針變量的名字爲p,則p+i的值是p+i*(p所指向的變量所佔的字節數)
指針變量不能相加,不能相乘, 不能相除,若是兩指針變量屬於同一數組,則能夠相減
指針變量能夠加減一整數,前提是最終結果不能超過指針
p+i 的值是p+i*(p所指向的變量所佔的字節數)
p- i 的值是p-i*(p所指向的變量所佔的字節數)
p++ <==> p+1 // 若是是int型,就是4字節,double型,就是8字節,可是都是指向的後一個元素
p-- <==> p-1
如何經過被調函數修改主調函數中一維數組的內容[如何界定]
兩個參數:1)存放數組首元素的指針變量;2)存放數組元素長度的整型變量
//Array_point_2.cpp # include <stdio.h> void Show_Array(int * p, int len) // a發送給了*p { // p[0] = -1; //p[0] == *p // p[2] = -1; //p[2] == *(p+2) == *(a+2) p[i]就是主函數的a[i] int i = 0; for (i=0; i<len; ++i) printf("%d\n", p[i]); } int main(void) { int a[5] = {1,2,3,4,5}; Show_Array(a, 5); // a等價於&a[0], &a[0]自己就是i // 經過寫一個數組名,數組長度,就能夠肯定一個數組, // 要想經過一個函數,訪問另外一個函數中的一個數組,只須要知道這個數組的首地址(數組第一個元素地址)和長度, // 在另外一個函數中就能夠任意訪問、修改主函數a[5]的值 //[Out]:1 2 3 4 5 // printf("%d\n", a[2]); //[Out]: -1 // printf("%d\n", a[0]); //[Out]: -1 return 0; }