記錄一下自己的第一次面試題
①尋找兩個連結串列中的第一個公共節點
②HTTP和TCP的區別
③C語言中的free問題
④SQL查詢語句
⑤索引為什麼能加速查詢
⑥二分查詢樹
⑦SQL內建語句,例如group,order,limit
⑧對介面的理解
⑨對最新技術的理解,例如區塊鏈
⑩資料庫引擎有哪些?各自優缺點。
①
思路:如果兩個連結串列有公共節點,那麼它們在第一個公共節點以後的節點都相同。
1)分別求出兩個連結串列的長度length1和length2;
2)求出兩個連結串列長度差dif;
3)讓長的連結串列先從頭往後先走dif步
4)連個連結串列同時走,直到指標相同為止,返回當前指標。
5)如果兩連結串列走到頭也地址不相同,則返回NULL
程式碼如下:
②/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: unsigned int GetListLength(ListNode* pHead){ unsigned int length = 0; ListNode* pNode = pHead; while(pNode != NULL){ length++; pNode = pNode->next; } return length; } ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { if(pHead1 == NULL || pHead2 == NULL) return NULL; ListNode* p1 = pHead1; ListNode* p2 = pHead2; unsigned int length1 = GetListLength(p1); unsigned int length2 = GetListLength(p2); if(length1 > length2){ while((length1--) > length2){ p1 = p1->next; } } else if(length2 > length1){//注意這裡一定是else if,用if會出錯,因為前面length1--導致的 while((length2--) > length1){ p2 = p2->next; } } while(p1 != NULL && p2 != NULL){ if(p1 == p2) return p1; else{ p1 = p1->next; p2 = p2->next; } } return NULL; } };
一、基本概念
1、TCP連線
手機能夠使用聯網功能是因為手機底層實現了TCP/IP協議,可以使手機終端通過無線網路建立TCP連線。TCP協議可以對上層網路提供介面,使上層網路資料的傳輸建立在“無差別”的網路之上。
建立起一個TCP連線需要經過“三次握手”:
第一次握手:客戶端傳送syn包(syn=j)到伺服器,並進入SYN_SEND狀態,等待伺服器確認;
第二次握手:伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;
第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手。
握手過程中傳送的包裡不包含資料,三次握手完畢後,客戶端與伺服器才正式開始傳送資料。理想狀態下,TCP連線一旦建立,在通訊雙方中的任何一方主動關閉連 接之前,TCP 連線都將被一直保持下去。斷開連線時伺服器和客戶端均可以主動發起斷開TCP連線的請求,斷開過程需要經過“四次握手”(過程就不細寫 了,就是伺服器和客戶端互動,最終確定斷開)
2、HTTP連線
HTTP協議即超文字傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用。
HTTP連線最顯著的特點是客戶端傳送的每次請求都需要伺服器回送響應,在請求結束後,會主動釋放連線。從建立連線到關閉連線的過程稱為“一次連線”。
1)在HTTP 1.0中,客戶端的每次請求都要求建立一次單獨的連線,在處理完本次請求後,就自動釋放連線。
2)在HTTP 1.1中則可以在一次連線中處理多個請求,並且多個請求可以重疊進行,不需要等待一個請求結束後再發送下一個請求。
由於HTTP在每次請求結束後都會主動釋放連線,因此HTTP連線是一種“短連線”,要保持客戶端程式的線上狀態,需要不斷地向伺服器發起連線請求。通常的 做法是即時不需要獲得任何資料,客戶端也保持每隔一段固定的時間向伺服器傳送一次“保持連線”的請求,伺服器在收到該請求後對客戶端進行回覆,表明知道客 戶端“線上”。若伺服器長時間無法收到客戶端的請求,則認為客戶端“下線”,若客戶端長時間無法收到伺服器的回覆,則認為網路已經斷開。
3、SOCKET原理
3.1套接字(socket)概念
套接字(socket)是通訊的基石,是支援TCP/IP協議的網路通訊的基本操作單元。它是網路通訊過程中端點的抽象表示,包含進行網路通訊必須的五種資訊:連線使用的協議,本地主機的IP地址,本地程序的協議埠,遠地主機的IP地址,遠地程序的協議埠。
應用層通過傳輸層進行資料通訊時,TCP會遇到同時為多個應用程式程序提供併發服務的問題。多個TCP連線或多個應用程式程序可能需要通過同一個 TCP協 議埠傳輸資料。為了區別不同的應用程式程序和連線,許多計算機作業系統為應用程式與TCP/IP協議互動提供了套接字(Socket)介面。應用層可以 和傳輸層通過Socket介面,區分來自不同應用程式程序或網路連線的通訊,實現資料傳輸的併發服務。
3.2 建立socket連線
建立Socket連線至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於伺服器端,稱為ServerSocket 。
套接字之間的連線過程分為三個步驟:伺服器監聽,客戶端請求,連線確認。
伺服器監聽:伺服器端套接字並不定位具體的客戶端套接字,而是處於等待連線的狀態,實時監控網路狀態,等待客戶端的連線請求。
客戶端請求:指客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描述它要連線的伺服器的套接字,指出伺服器端套接字的地址和埠號,然後就向伺服器端套接字提出連線請求。
連線確認:當伺服器端套接字監聽到或者說接收到客戶端套接字的連線請求時,就響應客戶端套接字的請求,建立一個新的執行緒,把伺服器端套接字的描述發給客戶 端,一旦客戶端確認了此描述,雙方就正式建立連線。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連線請求。
4、SOCKET連線與TCP連線
建立Socket連線時,可以指定使用的傳輸層協議,Socket可以支援不同的傳輸層協議(TCP或UDP),當使用TCP協議進行連線時,該Socket連線就是一個TCP連線。
5、Socket連線與HTTP連線
由於通常情況下Socket連線就是TCP連線,因此Socket連線一旦建立,通訊雙方即可開始相互發送資料內容,直到雙方連線斷開。但在實際網路應用 中,客戶端到伺服器之間的通訊往往需要穿越多箇中間節點,例如路由器、閘道器、防火牆等,大部分防火牆預設會關閉長時間處於非活躍狀態的連線而導 致 Socket 連線斷連,因此需要通過輪詢告訴網路,該連線處於活躍狀態。
而HTTP連線使用的是“請求—響應”的方式,不僅在請求時需要先建立連線,而且需要客戶端向伺服器發出請求後,伺服器端才能回覆資料。
很多情況下,需要伺服器端主動向客戶端推送資料,保持客戶端與伺服器資料的實時與同步。此時若雙方建立的是Socket連線,伺服器就可以直接將資料傳送給 客戶端;若雙方建立的是HTTP連線,則伺服器需要等到客戶端傳送一次請求後才能將資料傳回給客戶端,因此,客戶端定時向伺服器端傳送連線請求,不僅可以 保持線上,同時也是在“詢問”伺服器是否有新的資料,如果有就將資料傳給客戶端。
二、相互關係
首先,糾正一下我以前一直誤解的概念,我一直以為Http和Tcp是兩種不同的,但是地位對等的協議,雖然知道TCP是傳輸層,而http是應用層今天學習了下,知道了 http是要基於TCP連線基礎上的,簡單的說,TCP就是單純建立連線,不涉及任何我們需要請求的實際資料,簡單的傳輸。http是用來收發資料,即實際應用上來的。
第一:從傳輸層,先說下TCP連線,我們要和服務端連線TCP連線,需要通過三次連線,包括:請求,確認,建立連線。即傳說中的“三次握手協議”。
第一次:C傳送一個請求連線的位碼SYN和一個隨機產生的序列號給Seq,然後S收到了這些資料。
第二次:S收到了這個請求連線的位碼,啊呀,有人向我發出請求了麼,那我要不要接受他的請求,得實現確認一下,於是,傳送了一個確認碼 ACN(seq+1),和SYN,Seq給C,然後C收到了,這個是第二次連線。
第三次:C收到了確認的碼和之前傳送的SYN一比較,偶喲,對上了麼,於是他又傳送了一個ACN(SEQ+1)給S,S收到以後就確定建立連線,至此,TCP連線建立完成。
簡單就是:請求,確認,連線。
第二:從實際上的資料應用來說httP
在前面客戶端和應用伺服器建立TCP連線之後,就需要用http協議來傳送資料了,HTTP協議簡單來說,還是請求,確認,連線。
總體就是C傳送一個HTTP請求給S,S收到了這個http請求,然後返回給Chttp響應,然後C的中介軟體或者說瀏覽器把這些資料渲染成為了網頁,展示在使用者面前。
第一:傳送一個http請求給S,這個請求包括請求頭和請求內容:
request header:
包括了,1.請求的方法是POST/GET,請求的URL,http協議版本2.請求的資料,和編碼方式3是否有cookie和cooies,是否快取等。
post和get請求方式的區別是,get把請求內容放在URL後面,但是URL長度有限制。而post是以表單的形勢,適合要輸入密碼之類的,因為不在URL中顯示,所以比較安全。
request body:
即請求的內容.
第二:S收到了http請求,然後根據請求頭,返回http響應。
response header:包括了1.cookies或者sessions2.狀態嗎3.內容大小等
response body:
即響應的內容,包括,JS什麼的。
第三,C收到了以後,就由瀏覽器完成一系列的渲染,包括執行JS指令碼等。
這就是我所理解的webTCP,HTTP基礎知識,待續。。。。。
TCP是底層通訊協議,定義的是資料傳輸和連線方式的規範
HTTP是應用層協議,定義的是傳輸資料的內容的規範
HTTP協議中的資料是利用TCP協議傳輸的,所以支援HTTP也就一定支援TCP
HTTP支援的是www服務
而TCP/IP是協議
它是Internet國際網際網路絡的基礎。TCP/IP是網路中使用的基本的通訊協議。
TCP/IP實際上是一組協議,它包括上百個各種功能的協議,如:遠端登入、檔案傳輸和電子郵件等,而TCP協議和IP協議是保證資料完整傳輸的兩個基本的重要協議。通常說TCP/IP是Internet協議族,而不單單是TCP和IP。
③你在free(p)之後,最好加上p = NULL;
要不然容易導致野指標。你在free(p)之後,你只是使用
if(p != NULL)
你想的是用來進行防止誤用操作對吧。。
你進入了一個誤區,誤認為free(p)之後,p就指向了NULL,而其實不然。
free(p)的言外之意就是告訴編譯器:大家注意啦哈,這塊記憶體我現在不用了,你們誰想用就拿去用哈。而p在這裡你可以完全理解成就是這塊記憶體的地址,也就是告訴編譯器,這塊記憶體現在不被佔用了,而裡面的內容此時就是我們所說的“垃圾”,因為作為主人的我已經丟棄它了,裡面的內容就是不可控的。
注意p是個地址,你沒有強行置為空,那還是原來的那個值。只是裡面的內容不受控啦,有可能不會變,有可能會被改寫,而結果是未知的。”
之前在知乎上總是看到大牛們大書特書C語言記憶體管理機制的缺陷,野指標的種種危害。卻從未想過究竟什麼是“野指標”,今天遇到的這個問題就是野指標帶來的,看來自己對C指標的認識還不夠深刻,還需要更深層次的學習,特地寫下此文,加以反思。
看來水平離熟練使用C還差很遠,靜下心繼續反思吧。
⑤首先明白為什麼索引會增加速度,DB在執行一條Sql語句的時候,預設的方式是根據搜尋條件進行全表掃描,遇到匹配條件的就加入搜尋結果集合。如果我們對某一欄位增加索引,查詢時就會先去索引列表中一次定位到特定值的行數,大大減少遍歷匹配的行數,所以能明顯增加查詢的速度。
新增索引的話,首先去索引列表中查詢,而我們的索引列表是B類樹的資料結構,查詢的時間複雜度為O(log2N),定位到特定值得行就會非常快,所以其查詢速度就會非常快。
為什麼說B+-tree比B 樹更適合實際應用中作業系統的檔案索引和資料庫索引?
1) B+-tree的磁碟讀寫代價更低
B+-tree的內部結點並沒有指向關鍵字具體資訊的指標。因此其內部結點相對B 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入記憶體中的需要查詢的關鍵字也就越多。相對來說IO讀寫次數也就降低了。
舉個例子,假設磁碟中的一個盤塊容納16bytes,而一個關鍵字2bytes,一個關鍵字具體資訊指標2bytes。一棵9階B-tree(一個結點最多8個關鍵字)的內部結點需要2個盤快。而B+ 樹內部結點只需要1個盤快。當需要把內部結點讀入記憶體中的時候,B 樹就比B+ 樹多一次盤塊查詢時間(在磁碟中就是碟片旋轉的時間)。
2) B+-tree的查詢效率更加穩定
由於非終結點並不是最終指向檔案內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查詢必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
⑥二叉查詢樹(Binary Search Tree),也稱有序二叉樹(ordered binary tree),排序二叉樹(sorted binary tree),是指一棵空樹或者具有下列性質的二叉樹:
- 若任意節點的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
- 任意節點的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
- 任意節點的左、右子樹也分別為二叉查詢樹。
- 沒有鍵值相等的節點(no duplicate nodes)。
二叉查詢樹的性質:
二叉查詢樹本質上是一種二叉樹,所以上章講的二叉樹的性質他都有。
二叉查詢樹的思想:
二叉排序樹的查詢過程和次優二叉樹類似,通常採取二叉連結串列作為二叉排序樹的儲存結構。中序遍歷二叉排序樹可得到一個關鍵字的有序序列,一個無序序列可以通過構造一棵二叉排序樹變成一個有序序列,構造樹的過程即為對無序序列進行排序的過程。每次插入的新的結點都是二叉排序樹上新的葉子結點,在進行插入操作時,不必移動其它結點,只需改動某個結點的指標,由空變為非空即可。搜尋,插入,刪除的複雜度等於樹高,O(log(n)).
⑩在Mysql資料庫中,常用的引擎主要就是2個:Innodb和MyIASM。這篇文章將主要介紹這兩個引擎,以及該如何去選擇引擎,最後在提一下這2種引擎所使用的資料結構是什麼。
首先介紹一下Innodb引擎。
Innodb引擎提供了對資料庫ACID事務的支援。並且還提供了行級鎖和外來鍵的約束。它的設計的目標就是處理大資料容量的資料庫系統。它本身實際上是基於Mysql後臺的完整的系統。Mysql執行的時候,Innodb會在記憶體中建立緩衝池,用於緩衝資料和索引。但是,該引擎是不支援全文搜尋的。同時,啟動也比較的慢,它是不會儲存表的行數的。當進行Select count(*) from table指令的時候,需要進行掃描全表。
所以當需要使用資料庫的事務時,該引擎就是首選。由於鎖的粒度小,寫操作是不會鎖定全表的。所以在併發度較高的場景下使用會提升效率的。
接下來來說說MyIASM引擎。它是MySql的預設引擎,但不提供事務的支援,也不支援行級鎖和外來鍵。因此當執行Insert插入和Update更新語句時,即執行寫操作的時候需要鎖定這個表。所以會導致效率會降低。不過和Innodb不同的是,MyIASM引擎是儲存了表的行數,於是當進行Select count(*) from table語句時,可以直接的讀取已經儲存的值而不需要進行掃描全表。
所以,如果表的讀操作遠遠多於寫操作時,並且不需要事務的支援的。可以將MyIASM作為資料庫引擎的首先。
我們在來說說這兩種引擎的選擇。其實上面已經提到了。這裡我在補充了兩點:
1、大容量的資料集時趨向於選擇Innodb。因為它支援事務處理和故障的恢復。Innodb可以利用資料日誌來進行資料的恢復。主鍵的查詢在Innodb也是比較快的。
2、大批量的插入語句時(這裡是INSERT語句)在MyIASM引擎中執行的比較的快,但是UPDATE語句在Innodb下執行的會比較的快,尤其是在併發量大的時候。
最後我們再來說說兩種引擎所使用的索引的資料結構是什麼?答案是都是B+樹。
對於MyIASM引擎來說,B+樹的資料結構中儲存的內容實際上是實際資料的地址值。也就是說它的索引和實際資料是分開的,只不過使用索引指向了實際資料。這種索引的模式被稱為非聚集索引。
而Innodb引擎的索引的資料結構也是B+樹,只不過資料結構中儲存的都是實際的資料,這種索引有被稱為聚集索引。