瀏覽器獲取輸入的域名 [www.baidu.com]
瀏覽器向域名系統 DNS 請求解析 [www.baidu.com]的 IP 地址
DNS 解析出百度服務器的 IP 地址
瀏覽器與服務器創建 TCP 鏈接(默認端口 80)
瀏覽器發出 HTTP 請求,請求百度首頁
服務器經過 HTTP 請求把首頁文件發給瀏覽器
TCP 鏈接釋放
瀏覽器解析首頁文件,展現 web 界面
其實 C 和 C++的內存分區仍是有必定區別的,但此處不做區分:c++
1)棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等,其操做方式相似於數據結構中的棧。
2)堆區(heap) — 通常由程序員分配釋放, 若程序員不釋放,程序結束時可能由 OS 回收 ,注意它與數據結構中的堆是兩回事,分配方式卻是相似於鏈表
3)全局區(靜態區)(static)—,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。 - 程序結束後由系統釋放。
4)、文字常量區 —常量字符串就是放在這裏的。 程序結束後由系統釋放。
5)、程序代碼區—存放函數體的二進制代碼。
棧區與堆區的區別:程序員
1)堆和棧中的存儲內容:棧存局部變量、函數參數等。堆存儲使用 new、malloc 申請的變量等;
2)申請方式:棧內存由系統分配,堆內存由本身申請;
3)申請後系統的響應:棧——只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,不然將報異常提示棧溢出。堆——首先應該知道操做系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,而後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序;
4)申請大小的限制:Windows 下棧的大小通常是 2M,堆的容量較大;
5)申請效率的比較:棧由系統自動分配,速度較快。堆使用 new、malloc 等分配,較慢;
總結:棧區優點在處理效率,堆區優點在於靈活;web
內存模型:自由區、靜態區、動態區;根據 c/c++對象生命週期不一樣,c/c++的內存模型有三種不一樣的內存區域,即:自由存
根據 c/c++對象生命週期不一樣,c/c++的內存模型有三種不一樣的內存區域,即:自由存儲區,動態區、靜態區。
自由存儲區:局部非靜態變量的存儲區域,即日常所說的棧;
動態區: 用 new ,malloc 分配的內存,即日常所說的堆;
靜態區:全局變量,靜態變量,字符串常量存在的位置;
注:代碼雖然佔內存,但不屬於 c/c++內存模型的一部分;
快速排序的三個步驟:面試
(1)選擇基準:在待排序列中,按照某種方式挑出一個元素,做爲 "基準"(pivot);
(2)分割操做:以該基準在序列中的實際位置,把序列分紅兩個子序列。此時,在基準左邊的元素都比該基準小,在基準右邊的元素都比基準大;
(3)遞歸地對兩個序列進行快速排序,直到序列爲空或者只有一個元素。
基準的選擇:
對於分治算法,當每次劃分時,算法若都能分紅兩個等長的子序列時,那麼分治算法效率會達到最大。即:同一數組,時間複雜度最小的是每次選取的基準均可以將序列分爲兩個等長的;時間複雜度最大的是每次選擇的基準都是當前序列的最大或最小元素;
快排代碼實現:
咱們通常選擇序列的第一個做爲基數,那麼快排代碼以下:
`void quicksort(vector<int> &v,int left, int right)
{
if(left < right)//false 則遞歸結束
{
int key=v[left];//基數賦值
int low = left;
int high = right;
while(low < high) //當 low=high 時,表示一輪分割結束
{
while(low < high && v[high] >= key)//v[low]爲基數,從後向前與基數
比 較
{
high--;
}
swap(v[low],v[high]);
while(low < high && v[low] <= key)//v[high]爲基數,從前向後與基數
比 較
{
low++;
}
swap(v[low],v[high]);
}
//分割後,對每一分段重複上述操做
quicksort(v,left,low-1);
quicksort(v,low+1,right);
} }
`
注:上述數組或序列 v 必須是引用類型的形參,由於後續快排結果須要直接反映在原
序列中;
優化:
上述快排的基數是序列的第一個元素,這樣的對於有序序列,快排時間複雜度會達到
最差的 o(n^2)。因此,優化方向就是合理的選擇基數。
常見的作法「三數取中」法(序列過短還要結合其餘排序法,如插入排序、選擇排序
等),以下:
①當序列區間長度小於 7 時,採用插入排序;
②當序列區間長度小於 40 時,將區間分紅 2 段,獲得左端點、右端點和中點,咱們
對這三個點取中數做爲基數;
③當序列區間大於等於 40 時,將區間分紅 8 段,獲得左三點、中三點和右三點,分
別再獲得左三點中的中數、中三點中的中數和右三點中的中數,再將獲得的三個中數
取中數,而後將該值做爲基數。
具體代碼只是在上一份的代碼中將「基數賦值」改成①②③對應的代碼便可:
`int key=v[left];//基數賦值
if (right-left+1<=7) {
insertion_sort(v,left,right);//插入排序
return;
}else if(right-left+1<=8){
key=SelectPivotOfThree(v,left,right);//三個取中
}else{
//三組三個取中,再三個取中(使用 4 次 SelectPivotOfThree,此處不具體展現)
}
須要調用的函數:
void insertion_sort(vector<int> &unsorted,int left, int right) //插入排序算法
{
for (int i = left+1; i <= right; i++)
{
if (unsorted[i - 1] > unsorted[i])
{
int temp = unsorted[i];
int j = i;
while (j > left && unsorted[j - 1] > temp)
{
unsorted[j] = unsorted[j - 1];
j--;
}
unsorted[j] = temp;
}
}
}
int SelectPivotOfThree(vector<int> &arr,int low,int high)
//三數取中,同時將中值移到序列第一位
{
int mid = low + (high - low)/2;//計算數組中間的元素的下標
//使用三數取中法選擇樞軸
if (arr[mid] > arr[high])//目標: arr[mid] <= arr[high]
{
swap(arr[mid],arr[high]);
}
if (arr[low] > arr[high])//目標: arr[low] <= arr[high]
{
swap(arr[low],arr[high]);
}
if (arr[mid] > arr[low]) //目標: arr[low] >= arr[mid]
{
swap(arr[mid],arr[low]);
}
//此時,arr[mid] <= arr[low] <= arr[high]
return arr[low];
//low 的位置上保存這三個位置中間的值
//分割時能夠直接使用 low 位置的元素做爲樞軸,而不用改變分割函數了
}
`
這裏須要注意的有兩點:
①插入排序算法實現代碼;②三數取中函數不只僅要實現取中,還要將中值移到最低位,從而保證原分割函數依然可用。算法
四條從效果上第一條影響最大,後面愈來愈小。數據庫
① SQL 語句及索引的優化
② 數據庫表結構的優化
③ 系統配置的優化
④ 硬件的優化
①若是兩個鏈表相交,則從相交點開始,後面的節點都相同,即最後一個節點確定相
同;
②從頭至尾遍歷兩個鏈表,並記錄鏈表長度,當兩者的尾節點不一樣,則兩者確定不相
交;
③尾節點相同,若是 A 長爲 LA,B 爲 LB,若是 LA>LB,則 A 前 LA-LB 個先跳過;
——更多如鏈表相關經典問題:求單向局部循環鏈表的入、將兩個有序鏈表合併合成
一個有序鏈表、鏈表逆序、求倒數第 K 個節點,判斷是否有環等。數組
malloc 和 new 的區別:瀏覽器
1)malloc 與 free 是 C++/C 語言的標準庫函數,new/delete 是 C++的運算符。它們均可用於申請動態內存和釋放內存;
2)new 返回指定類型的指針,而且能夠自動計算所須要大小。而 malloc 則必需要由程序員計算字節數,而且在返回後強行轉換爲實際類型的指針;
3)new/delete 在對象建立的同時能夠自動執行構造函數初始化,在對象在消亡以前會自動執行析構函數。而 malloc 只管分配內存,並不能對所得的內存進行初始化, 因此獲得的一片新內存中,其值將是隨機的;既然 new/delete 的功能覆蓋了 malloc/free,爲何 C++還要保留 malloc/free?由於 C++程序常常要調用 C 函數,而 C 程序只能用 malloc/free 管理動態內存。new/delete、malloc/free 底層實現原理:
概述:new/delete 的底層實現是調用 malloc/free 函數實現的,而 malloc/free 的底
層實現也不是直接操做內存而是調用系統 API 實現的。
new/delete 的兩種分配方式原理圖以下:
注意,針對上圖最末尾所述的「new[]/delete[]時會多開闢 4 字節用於存儲對象個
數」,做以下說明:服務器
①對於內置類型:數據結構
new []不會在首地址前 4 個字節定義數組長度。delete 和 delete[]是同樣的執行效果,都會刪除整個數組,要刪除的長度從 new 時便可知道。
②對於自定義類型:
new []會在首地址前 4 個字節定義數組長度。當 delete[]時,會根據前 4 個字節所定義的長度來執行析構函數刪除整個數組。若是隻是 delete 數組首地址,只會刪除第一個對象的值。
還有這麼多面試題刷不知道夠不夠,須要面試題的能夠分享哦