華爲一面:java
一、圖的表示方式?算法
(1)鄰接表法:鄰接表的核心思想就是針對每一個頂點設置一個鄰居表。 編程
以上面的圖爲例,這是一個有向圖,分別有頂點a, b, c, d, e, f, g, h共8個頂點。使用鄰接表就是針對這8個頂點分別構建鄰居表,從而構成一個8個鄰居表組成的結構,這個結構就是咱們這個圖的表示結構或者叫存儲結構。安全
a, b, c, d, e, f, g, h = range(8)服務器
N = [{b, c, d, e, f}, # a 的鄰居表網絡
{c, e}, # b 的鄰居表併發
{d}, # c 的鄰居表函數
{e}, # d 的鄰居表this
{f}, # e 的鄰居表spa
{c, g, h}, # f 的鄰居表
{f, h}, # g 的鄰居表
{f, g}] # h 的鄰居表
(2)鄰接矩陣:鄰接矩陣的核心思想是針對每一個頂點設置一個表,這個表包含全部頂點,經過True/False來表示是不是鄰居頂點。仍是針對上面的圖,分別有頂點a, b, c, d, e, f, g, h共8個頂點。使用鄰接矩陣就是針對這8個頂點構建一個8×8的矩陣組成的結構,這個結構就是咱們這個圖的表示結構或存儲結構。
a, b, c, d, e, f, g, h = range(8)
N = [[0, 1, 1, 1, 1, 1, 0, 0], # a的鄰接狀況
[0, 0, 1, 0, 1, 0, 0, 0], # b 的鄰居表
[0, 0, 0, 1, 0, 0, 0, 0], # c 的鄰居表
[0, 0, 0, 0, 1, 0, 0, 0], # d 的鄰居表
[0, 0, 0, 0, 0, 1, 0, 0], # e 的鄰居表
[0, 0, 1, 0, 0, 0, 1, 1], # f 的鄰居表
[0, 0, 0, 0, 0, 1, 0, 1], # g 的鄰居表
[0, 0, 0, 0, 0, 1, 1, 0]] # h 的鄰居表
二、圖的遍歷方式?
一般有兩種遍歷圖的方法:深度優先遍歷和廣度優先遍歷。它們對無向圖和有向圖都適用。圖的遍歷算法是求解圖的連通性問題、拓撲排序和求關鍵路徑等算法的基礎。
1) 深度優先遍歷: 從圖中某個頂點v出發,訪問該頂點,而後依次從v的未被訪問的鄰接點出發繼續深度優先遍歷圖中的其他頂點,直至圖中全部與v有路徑相通的頂點都被訪問完爲止;若此時尚有頂點未被訪問,則選擇一個頂點做爲起始點,重複上述過程,直到全部的頂點都被訪問。深度優先遍歷是一個遞歸的過程。
2) 廣度優先遍歷:首先,從圖的某個頂點v出發,依次訪問與v相鄰的未被訪問的頂點,而後分別從這些頂點出發,廣度優先遍歷,直至全部的頂點都被訪問完。
如上圖中,廣度優先遍歷獲得的序列爲:
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 ->7
三、進程的通訊方式?
進程間通訊(IPC,InterProcess Communication)是指在不一樣進程之間傳播或交換信息。IPC的方式一般有管道(包括無名管道和命名管道)、消息隊列、信號量、共享存儲、Socket、Streams等。其中 Socket和Streams支持不一樣主機上的兩個進程IPC。
以Linux中的C語言編程爲例。
1、管道:管道,一般指無名管道,是 UNIX 系統IPC最古老的形式。
特色:它是半雙工的(即數據只能在一個方向上流動),具備固定的讀端和寫端;它只能用於具備親緣關係的進程之間的通訊(也是父子進程或者兄弟進程之間);它能夠當作是一種特殊的文件,對於它的讀寫也可使用普通的read、write 等函數;可是它不是普通的文件,並不屬於其餘任何文件系統,而且只存在於內存中。
2、FIFO:也稱爲命名管道,它是一種文件類型。
特色:FIFO能夠在無關的進程之間交換數據,與無名管道不一樣;FIFO有路徑名與之相關聯,它以一種特殊設備文件形式存在於文件系統中。
3、消息隊列:是消息的連接表,存放在內核中。一個消息隊列由一個標識符(即隊列ID)來標識。
特色:消息隊列是面向記錄的,其中的消息具備特定的格式以及特定的優先級;消息隊列獨立於發送與接收進程,進程終止時,消息隊列及其內容並不會被刪除;消息隊列能夠實現消息的隨機查詢,消息不必定要以先進先出的次序讀取,也能夠按消息的類型讀取。
4、信號量:信號量(semaphore)與已經介紹過的 IPC 結構不一樣,它是一個計數器。信號量用於實現進程間的互斥與同步,而不是用於存儲進程間通訊數據。
特色:信號量用於進程間同步,若要在進程間傳遞數據須要結合共享內存;信號量基於操做系統的 PV 操做,程序對信號量的操做都是原子操做;每次對信號量的 PV 操做不只限於對信號量值加 1 或減 1,並且能夠加減任意正整數;支持信號量組。
5、共享內存:共享內存(Shared Memory),指兩個或多個進程共享一個給定的存儲區。
特色:共享內存是最快的一種 IPC,由於進程是直接對內存進行存取;由於多個進程能夠同時操做,因此須要進行同步;信號量+共享內存一般結合在一塊兒使用,信號量用來同步對共享內存的訪問。
五種通信方式總結
管道:速度慢,容量有限,只有父子進程能通信
FIFO:任何進程間都能通信,但速度慢
消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完數據的問題
信號量:不能傳遞複雜消息,只能用來同步
共享內存區:可以很容易控制容量,速度快,但要保持同步,好比一個進程在寫的時候,另外一個進程要注意讀寫的問題,至關於線程中的線程安全,固然,共享內存區一樣能夠用做線程間通信,不過沒這個必要,線程間原本就已經共享了同一進程內的一塊內存
4、java判斷可回收的垃圾對象?
1. 引用計數算法
爲對象添加一個引用計數器,當對象增長一個引用時計數器加 1,引用失效時計數器減 1。引用計數爲 0 的對象可被回收。 在兩個對象出現循環引用的狀況下,此時引用計數器永遠不爲 0,致使沒法對它們進行回收。正是由於循環引用的存在,所以 Java 虛擬機不使用引用計數算法
2. 可達性分析算法
以 GC Roots 爲起始點進行搜索,可達的對象都是存活的,不可達的對象可被回收。
Java 虛擬機使用該算法來判斷對象是否可被回收,GC Roots 通常包含如下內容:
5、實現線程同步的方法?
1.同步方法
即有synchronized關鍵字修飾的方法(全部訪問狀態變量的方法都必須進行同步),此時充當鎖的對象爲調用同步方法的對象。在調用該方法前,須要得到內置鎖,不然就處於阻塞狀態。
2.同步代碼塊
即有synchronized關鍵字修飾的語句塊。鎖的粒度更細,而且充當鎖的對象不必定是this,也能夠是其它對象,使用起來更加靈活。
3.使用特殊域變量(volatile—不能保證原子性)實現線程同步
(1).volatile關鍵字爲域變量的訪問提供了一種免鎖機制;
(2).使用volatile修飾域至關於告訴虛擬機該域可能會被其餘線程更新;
(3).所以每次使用該域就要從新計算,而不是使用寄存器中的值;
(4).volatile不會提供任何原子操做,它也不能用來修飾final類型的變量;
4.使用重入鎖實現線程同步
ReentrantLock類是可重入、互斥、實現了Lock接口的鎖,它擁有synchronized相同的併發性和內存語義,此外還多了鎖投票,定時鎖等候和中斷鎖等候。
線程A和B都要獲取對象O的鎖定,假設A獲取了對象O鎖,B將等待A釋放對O的鎖定;
若是使用synchronized,若是A不釋放,B將一直等下去,不能被中斷;
若是使用ReentrantLock,若是A不釋放,可使B在等待了足夠長的時間之後,中斷等待,而幹別的事情
5.使用局部變量實現線程同步
若是使用ThreadLocal管理變量,則每個使用該變量的線程都得到該變量的副本,副本之間相互獨立,這樣每個線程均可以隨意修改本身的變量副本,而不會對其餘線程產生影響。
6、雙向鏈表中刪除一個節點:假設須要被刪除的節點稱之爲delNode?
p->prior->next=p->next;
p->next->prior->p=p->prior;
7、項目介紹。。。。。blablabla
8、TCP三次握手
假設 A 爲客戶端,B 爲服務器端。
三次握手的緣由
第三次握手是爲了防止失效的鏈接請求到達服務器,讓服務器錯誤打開鏈接。
客戶端發送的鏈接請求若是在網絡中滯留,那麼就會隔很長一段時間才能收到服務器端發回的鏈接確認。客戶端等待一個超時重傳時間以後,就會從新請求鏈接。可是這個滯留的鏈接請求最後仍是會到達服務器,若是不進行三次握手,那麼服務器就會打開兩個鏈接。若是有第三次握手,客戶端會忽略服務器以後發送的對滯留鏈接請求的鏈接確認,不進行第三次握手,所以就不會再次打開鏈接。
9、四次揮手
如下描述不討論序號和確認號,由於序號和確認號的規則比較簡單。而且不討論 ACK,由於 ACK 在鏈接創建以後都爲 1。
四次揮手的緣由
客戶端發送了 FIN 鏈接釋放報文以後,服務器收到了這個報文,就進入了 CLOSE-WAIT 狀態。這個狀態是爲了讓服務器端發送還未傳送完畢的數據,傳送完畢以後,服務器會發送 FIN 鏈接釋放報文。
客戶端接收到服務器端的 FIN 報文後進入此狀態,此時並非直接進入 CLOSED 狀態,還須要等待一個時間計時器設置的時間 2MSL。這麼作有兩個理由:
華爲二面
人生理想之類的