主頁 > 軟體設計 > 跟我一起學資料結構(2)從陣列 到 鏈表

跟我一起學資料結構(2)從陣列 到 鏈表

2020-12-21 12:29:51 軟體設計

在這里插入圖片描述

思維導圖在這個系列寫的差不多的時候再整理吧,


文章目錄

    • 指標和動態記憶體分配
      • 參考&
        • 將參考用于結構
        • 何時使用參考引數?
      • 指標
        • 指標和const
        • 通過指標回傳字串的函式
        • 通過指標回傳結構
        • 函式指標
          • 宣告函式指標
          • 函式指標用武之地
          • 關于指標的一些思考
    • 陣列
      • STL陣列Vector
        • Vector基本函式使用
        • Vector的資料結構
      • 聯合體union
    • LeetCode精選題集
      • Vector篇
        • 1、參考傳參
        • 2、快慢指標
        • 3、map、set的使用
    • 結語

指標和動態記憶體分配

指標是C語言的基本概念,C語言中指標無處不在,實際上,每種資料型別,都有相應的指向T的指標型別,
指標型別變數存放的值,實際上就是記憶體地址,指標型別有兩個最基本的操作:

&:取地址操作 
*:去參考 (間接參考)操作

參考&

首先,&不是地址運算子,而是型別識別符號的一種,就像*也不是指標運算子一樣,

就像char* 意為指向char的指標一樣,int& 意為指向int 的參考,

栗子來一顆:

int a;
int &at = a;
//上述宣告允許將at和a互換,它們指向相同的值和記憶體單元,就像連體嬰一樣,

上面這個栗子其實很有內涵在里面
我為什么不寫成下面這個形式呢?

int a;
int &at;
at = a;

在指標中是可以的,但是&不允許,&必須在宣告時將其初始化,

參考經常被用作函式引數,使得函式中的變數名成為呼叫程式中變數的別名,這種呼叫方法我一直搞得暈暈的,正好這次一次性根除,這種傳遞引數的方法稱為按參考傳遞,按參考傳遞允許被呼叫函式能夠訪問呼叫函式中的變數,這是C++相比C的一個超越,
來個經典的栗子:

void swap_a(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

//順便來個指標的
void swap_b(int *a,int *b)
{
	int temp;
	temp = *a;	//a,b是指標,*a,*b才是int
	*a = *b;
	*b = temp;
}

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	int d = 4;
	swap_a(a,b);	//看仔細咯,這個是參考呼叫
	swap_b(&a,&b);	//看仔細咯,這個是指標呼叫
	//如果理解不了,這樣理解:引數中的*和&只是走個過場,告訴人家那個引數是什么型別的
	//呼叫函式時的引數是a,不是*a,也不是&a
	//所以&a傳的這個a是一個int型別,而*a的這個a就是指標,地址,所以要取地址傳給它
	//雖然我語文不好,但是都講到這份上了那應該是可以理解了
	return 0;
}

如果你的意圖是讓函式使用傳給它的資訊,又不想把這些資訊進行改動,那么應該使用const,
將參考引數宣告為const資料的好處有這些:

防止無意中被修改,
使用const引數可以兼容非const傳參,

將參考用于結構

C++引入參考主要就是為了和結構和類,
它還通過讓函式回傳指向結構的參考而增添了一個有趣的特點,這與回傳結構有所不同,

//代碼太長,放段偽代碼吧
struct Str
{
};

Str& test(Str &a,const Str &b)	
{
	//從b中取值,對a進行填充
	return a;//其實可以做void型別,沒必要多此一舉
}

int main()
{
	Str a,b,c;
	//b是有初值的,這是偽代碼
	c = test(a,b);
	return 0;
}

如果test函式回傳一個結構,而不是指向結構的參考,相當于把整個結構體復制到一個臨時位置,再將這個拷貝復制給c,但是現在回傳值為參考,將直接將a復制到c,效率更高

回傳參考時最重要的一點是:應避免回傳函式終止時將不再存在的記憶體單元的參考
下面是一個反面教材:

Str& test(const Str &d)
{
	Str &e;
	···
	return e;
}

何時使用參考引數?

程式員能夠修改呼叫函式中的資料物件,
通過傳遞參考而不是整個資料物件,可以提高程式的運行速度,

指標

指標和const

將const用于指標有一些很微妙的地方,
可以用兩種不同的方式將const關鍵字用于指標,

int age = 20; const int * pt = &age;
//該宣告指出,pt指向一個const int,因此不能使用pt來修改這個值,
//現在來看一個很微妙的問題:其實age并不是一個常量,只是對于pt來說,它是一個常量,
//就是說age可以改,只不過不能用pt來改而已,

注意點:不允許將常量資料賦值給非常量指標,個中理由就不用多解釋了吧,

const int age = 20; int * pt = &age;

int sloth = 80; int * const finger = &sloth;
#這種宣告格式使得這個指標只能指向sloth,不過可以通過這個指標修改sloth的值,

通過指標回傳字串的函式

現在,假設需要一個回傳字串的函式,是的,函式無法回傳一個字串,但是可以回傳字串的地址,這樣效率更高,

void test(char *rc)
{
	···
	memset(rc,字串);
	···
}

相當于是使用回呼函式,我個人比較喜歡這一套模式,

通過指標回傳結構

具體操作參考第二點,
當然,這里還有另外的應用場景:

void test2(const JieGouTi1 *a,JieGouTi2 *b)
{
	//將a中的某些值賦值給b
}
//這里有一個注意點,傳進去賦值的結構體指標最好用const.

函式指標

關于為什么要使用函式指標,我的理解還不是很深刻,畢竟功力不足,但是我知道那些回呼函式都是用函式指標的,所以對函式指標必須要理解好,
這叫啥,“但行好事,莫問為啥”,

函式指標完成任務的流程是這樣的:

獲取函式的地址
宣告一個函式指標
使用函式指標來呼叫函式
獲取函式地址

獲取函式地址那是比較簡單的事,如果說 void Hanshu();這是一個函式,那么它的地址就是 Hanshu,
如果函式Hanshubaba();要呼叫這個函式,是這樣的:Hanshubaba(Hanshu);
切記不能寫成:Hanshubaba(Hanshu());

宣告函式指標

假設現在有這么一個函式:int test3(void *arg); //這個arg引數,回呼函式里面用,要解釋有點長,
現在要將之改成函式指標形式:int (*test3)(void *arg);

首先,將test3更換成(*test3),因此,(*test3)也是函式,那么test3就是函式指標,
為宣告優先級,需要將 *test3 括號起來,

函式指標用武之地

如果你非要我說函式指標存在的意義,那我也真不好給你扯個所以然出來,那我就,舉幾個用得到的地方吧:

自定義排序/搜索

不同的模式(如策略,觀察者)

回呼
關于指標的一些思考

前面說到,將指標作為引數傳入,在函式內部對指標進行修改,函式結束后指標的修改將被保留,
因為指標傳參代表著地址傳參,

解惑:如何讓對指標引數的修改不被保存,

看個栗子:

class B {
	char* b;
public:
	B() {
		b = new char[5];
		strcpy(b,"aaaa");
	}
	char* get_b() { return b; }
};

class A {
private:
	char* a;
public:
	A(B* temp) { a = temp->get_b(); };

	void set_A() { 
		strcpy(a, "kkkk");	//頂替掉了
	}
};

int main() {
	B* b = new B();
	A* a = new A(b);
	a->set_A();
	cout << b->get_b() << endl;

	return 0;
}

結局列印出來的 b,就是“kkkk”,
那為什么會這樣?前面解釋過了,a、b都是對記憶體地址的映射,對a進行修改,就是對地址上的資料進行修改,而b只不過是地址的一個映射而已,讀取b,就是讀取地址上的東西,那本質已經被改了,讀出來的東西自然不一樣,

再看個例子:

void Del (POINT_T * the_head, int index)
{
	POINT_T *pFree=NULL;
	
	POINT_T *pNode=the_head;
	int flag=0;
	while (pNode->next!=NULL)
	{
		if(flag==index-1)
		{
			pFree=pNode->next;				//再指向資料域就爆了
			pNode->next=pNode->next->next;
			free(pFree->pData);
			free(pFree);
			break;
		}
		pNode=pNode->next;
		flag++;	
	}	
}

這是鏈表的一個例子,那可能會納悶兒,為什么對 pNode執行了 pNode=pNode->next;操作,而the_head卻沒有跟著變呢?
原因很簡單,pNode->next也是一個映射地址,這句話的意思就是用一個新的地址映射,頂替掉那個舊的,使得指標pNode指向一塊新的地址,和the_head失去聯系,


陣列

我們把一組資料的集合稱為陣列(Array),它所包含的每一個資料叫做陣列元素(Element),所包含的資料的個數稱為陣列長度,
陣列是一個整體,它的記憶體是連續的;也就是說,陣列元素之間是相互挨著的,彼此之間沒有一點點縫隙,
在這里插入圖片描述

不再贅言,

STL陣列Vector

C語言的陣列就不多說,STL的陣列那不能少說啊,

Vector是STL中一個很常用的容器,
作用:Vector可以理解為是一個可以存放 任意的統一種類的資料的動態陣列

能來看的對vector應該是有了解的,閑話不多說,

Vector的資料結構與array非常相似,不同的地方在于array是靜態的,一旦確定了范圍之后便不能改變(不定長陣列零擔別論),
要換個更大的空間是比較麻煩的,一切都得自己手動來,
Vector是動態分配空間的,相對比較友好,如果需要擴容的話它的內部機制會自己去處理,

Vector基本函式使用

  1. 創建
#include<vector>

vector<int> test;	//初始化一個Vector實體,用于存放int型資料,實體名字叫test

vector<int> test2 = test;	//以test1為標準創建test2

再看一個vector<int>test3(10);
創建一個vector容器,大小為10,內容默認置空
不是很建議這種做法啊,往里面插成段的值的時候只能插入第一個,后面就無法插入了,
再說了,你不用自己分配空間,STL都給你安排的好好的,

當然,初始化方式千千萬,放多了反而讓人眼花繚亂,會基本的最實用的夠了,

  1. 插入元素
test.insert(test.begin()+i,a);	//在第i個元素前插入a

test.insert(test.begin()+i,te2.begin(),te2.end());	
//插入一段相同資料型別資料,第一個引數放插入位置(指標/迭代器形式),第二三個引數放待插入元素起始位置

test.push_back(a);	//往尾部插入
  1. 洗掉元素
test.erase(test.begin());
test.erase(test.begin(),test.begin()+5);//洗掉區間(第一個元素到第五個元素)

test.clear();	//清空

test.pop_back();	//洗掉尾部元素

洗掉呢,還有個比較靈活的方式:

test.erase(it);	//這個it是迭代器

關于洗掉有一個必須·要注意的點:不要在foreach的時候進行洗掉操作,如果你一定要在遍歷的時候進行洗掉,你最好看一下下一行那個鏈接,

  1. 遍歷元素
    當然,你可以使用陣列下標形式訪問元素,因為vector多載了 [] 操作,不過不建議,雖然是很方便,但是有諸多限制,要是隨便就任你操作資料,那人家封裝起來干什么?
    我們應該養成使用下面這種迭代器訪問的方式,
vector<int>::iterator it;	//初始化一個vector<int>型別的迭代器
for(it = test.begin();it!=test.end();it++)	//從頭遍歷到尾
{
	cout<<*it<<endl;	//取出內容
}

關于迭代器還需要知道的是:vector的迭代器支持前后向,及多載了 +,—,++,-- 操作,

還有一個叫at()的函式,這個好用,

test.at(2);		//用這個比直接用下標要好的地方在于它會檢測越界

(明面上是這么說啊,其實我自己寫代碼也喜歡用下標定位)

  1. 頭尾指標
    這四個函式的區別要清楚:begin()、end()、front()、back(),我喜歡稱它們為頭尾指標,
    我也不知道為什么有人要就這些區別長篇大論,
begin():指向容器的第一個元素的地址,
front():指向容器的第一個元素的值,
end():和begin()配套
back():和front()配套
  1. 容器容量
test.size();	//容器已存入資料量
test.capacity();	//容器還能存多少資料量

其實不用擔心容器不夠大,容量要滿的時候它會自己擴容,

  1. 排序
#include<algorithm>
/*test.*/sort(test.begin(),test.end());	//從頭到尾,默認從小到大排序
這里要非常注意,前面那個test. 被我注釋掉了,因為sort是屬于演算法范疇,不是容器的類方法,

//一般排序都是要自定義排序的:
bool Comp(const int &a,const int &b)
{
    return a>b;
}
sort(test.begin(),test.end(),Comp);	//這樣就降序排序, 
  1. 其他

swap(test,test2);	//交換test和test2中的資料

test.resize(20);	//重置大小

reverse(test);		//元素翻轉

如果要問為什么沒有 “修改資料的部分”,參見第四點“遍歷資料”,


10、unique()函式

這個函式用來清理容器中的重復項,但前提是容器經過排序了,
而且,它不提供洗掉操作,只是把重復項移到容器后面的部分,所以直接size()的話大小是不會變的,
如果要清理重復項,這樣:nums.erase(unique(nums.begin(),nums.end()),nums.end());


最后再提一下兩個頭檔案:

#include<vector>	//vector類相關
#include<algorithm>	//容器演算法

vector的元素不僅僅可以是int,double,string,還可以是結構體,但是要注意:結構體要定義為全域的,否則會出錯,

特別注意:

使用vector需要注意以下幾點:

1、如果你要表示的向量長度較長(需要為向量內部保存很多數),容易導致記憶體泄漏,而且效率會很低;

2、Vector作為函式的引數或者回傳值時,需要注意它的寫法:

double Distance(vector&a, vector&b) 其中的“&”絕對不能少!!!


Vector的資料結構

所謂動態增添大小,并不是在原有空間之后再開辟空間,顯然那也不太現實,
而是以原大小的兩倍大小尋找一塊新空間,將內容真實的拷貝過去,然后釋放原空間,
不過就算洗掉元素過半也不會將記憶體放出來,

但是,需要牢記的一點是:對于Vector的一切操作,一旦引起空間的重新分配,那么指向原有空間的迭代器將會全部失效,

關于這點,我也做了一個測驗代碼:
可測可不測,結果我都注釋好了

#include <iostream>

#include<vector>

using namespace std;

int main()
{
    vector<int> vec1;
    //vector<int>::iterator it1 = vec1.begin();
    //放這里試試
    vec1.push_back(1);
     cout<<"left size :"<<vec1.capacity()<<endl;	//1
    vec1.push_back(6);
     cout<<"left size :"<<vec1.capacity()<<endl;	//2
    vec1.push_back(5);
     cout<<"left size :"<<vec1.capacity()<<endl;	//4
    vec1.push_back(4);
     cout<<"left size :"<<vec1.capacity()<<endl;	//4
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    //vector<int>::iterator it1 = vec1.begin();
    //放這里試試
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    vec1.push_back(3);
     cout<<"left size :"<<vec1.capacity()<<endl;	//8
    vec1.push_back(2);
     cout<<"left size :"<<vec1.capacity()<<endl;	//16

    vector<int>::iterator it1 = vec1.begin();
//這個回圈用于在6之后插入4
    while (it1 != vec1.end())
    {
        if (3 == *it1)
        {
            vec1.insert(it1+1, 4);
            cout<<"insert:"<<*it1<<endl;
        }
        it1++;
    }

//執行完插入操作,將值全部列印
    for(it1 = vec1.begin();it1!=vec1.end();it1++)
    {
        cout<<*it1<<endl;
    }
    cout<<"it1over"<<endl;

//準備執行對元素‘3’的洗掉
    vector<int>::iterator it2 = vec1.begin() ;
    while (it2 != vec1.end())
    {
        if (3 == *it2)
        {
             //it2 =vec1.erase(it2);
             vec1.erase(it2);	//這里有沒有都一樣,都指向洗掉之后的那個位置
             cout<<"delete:"<<*it2<<endl;
        }
        else
            it2++;
    }
//執行完洗掉操作,將容器資料進行列印
    for(it2 = vec1.begin();it2!=vec1.end();it2++)
    {
        cout<<*it2<<endl;
    }
    cout<<"it2over"<<endl;

//為測驗方便,這里直接清空Vector,看看它放不放空間
    vec1.clear();
    cout<<"clear left size :"<<vec1.capacity()<<endl;	//16
    return 0;
}


聯合體union

聯合體,又叫共用體,很直接,就是多個資料共同使用同一塊空間,

分配空間準則:分配共用體中最大資料型別的空間大小,

記憶體共用準則:

  1. 同等大小的資料視為同一資料(這個要小心,例如long int 和int共存時,修改一個另一個就會隨之改變)
  2. 大型別優先初始化,看示例:
#include<iostream>

using namespace std;

union var{
    long int l;	//4個位元組
    double i;	//8個位元組
};

int main(){
    union var v;
    v.i = 6.2;	
    v.l = 5;
//    v.i = 6.2;	//如果放在這里,會將v.l覆寫

    cout<<v.i<<endl;
    cout<<v.l<<endl;

    return 0;
}

可以拿去測驗,

根據union固定首地址和union按最大需求開辟一段記憶體空間兩個特征,可以發現,所有表面的定義都是虛的,所謂聯合體union,就是在記憶體給你劃了一個足夠用的空間,往里邊扔什么資料誰管得到?
這個如果有興趣的朋友可以自己去試一下將共用體物件強轉,


LeetCode精選題集

Vector篇

1、參考傳參

先來看個題目:
等下也是用這個題目

給定一個排序陣列,你需要在 原地 洗掉重復出現的元素,使得每個元素只出現一次,回傳移除后陣列的新長度,
不要使用額外的陣列空間,你必須在 原地 修改輸入陣列 并在使用 O(1) 額外空間的條件下完成,

示例 1:

給定陣列 nums = [1,1,2], 
函式應該回傳新的長度 2, 并且原陣列 nums 的前兩個元素被修改為 1, 2, 
你不需要考慮陣列中超出新長度后面的元素,
示例 2:

給定 nums = [0,0,1,1,1,2,2,3,3,4],
函式應該回傳新的長度 5, 并且原陣列 nums 的前五個元素被修改為 0, 1, 2, 3, 4,
你不需要考慮陣列中超出新長度后面的元素,

說明:
為什么回傳數值是整數,但輸出的答案是陣列呢?
請注意,輸入陣列是以「參考」方式傳遞的,這意味著在函式里修改輸入陣列對于呼叫者是可見的,
你可以想象內部操作如下:

// nums 是以“參考”方式傳遞的,也就是說,不對實參做任何拷貝
int len = removeDuplicates(nums);

// 在函式里修改輸入陣列對于呼叫者是可見的,
// 根據你的函式回傳的長度, 它會列印出陣列中該長度范圍內的所有元素,
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
著作權歸領扣網路所有,商業轉載請聯系官方授權,非商業轉載請注明出處,

以前只知道指標有這種騷操作,現在知道參考也有這種騷操作了,

2、快慢指標

對于上面這題的題解,便可以采用快慢指標的辦法,
在這里插入圖片描述

不用快慢指標也可以,不過本文不是為了說誰的辦法優秀,這題也不能體現出快慢指標的多少優越性,但是重要的是學到這個思路不是嗎,

可以考慮一下下面這道題:

給你一個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出所有滿足條件且不重復的三元組,

注意:答案中不可以包含重復的三元組,
示例:
給定陣列 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合為:

[
  [-1, 0, 1],
  [-1, -1, 2]
]

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/3sum
著作權歸領扣網路所有,商業轉載請聯系官方授權,非商業轉載請注明出處,

3、map、set的使用

以下是一個使用set的示例:
給定一個 m x n 的矩陣,如果一個元素為 0,則將其所在行和列的所有元素都設為 0,請使用原地演算法,

示例 1:
輸入:

[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]

輸出:

[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

輸入:

[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]

輸出:

[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

進階:

一個直接的解決方案是使用 O(mn) 的額外空間,但這并不是一個好的解決方案,
一個簡單的改進方案是使用 O(m + n) 的額外空間,但這仍然不是最好的解決方案,
你能想出一個常數空間的解決方案嗎?

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/set-matrix-zeroes
著作權歸領扣網路所有,商業轉載請聯系官方授權,非商業轉載請注明出處,

我的解法:

void setZeroes(vector<vector<int>>& matrix) {
    if(matrix.empty())
        return;
    int r = matrix.size();
    int c = matrix[0].size();

    set<int> rs;
    set<int> cs;
    set<int>::iterator sit;

    //將有0的行列提取出來
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c; j++)
        {
            if (matrix[i][j] == 0)
            {
                rs.insert(j);
                cs.insert(i);
            }
        }
    }

    if (!cs.empty())
    {
        int a = c;
        vector<int> temp;
        while (a > 0)
        {
            temp.push_back(0);
            a--;
        }
        
        //將行清零
        for (sit = cs.begin(); sit != cs.end(); sit++)
        {
            matrix[*sit] = temp;
        }
    }

    //將列清零
    if (!rs.empty())
    {
        for (sit = rs.begin(); sit != rs.end(); sit++)
        {
            for (int k = 0; k< r; k++)
            {
                matrix[k][*sit] = 0;
            }
        }
    }
}

思路:
在這里插入圖片描述
接下來是一個map的使用示例:

給定一個字串陣列,將字母異位詞組合在一起,字母異位詞指字母相同,但排列不同的字串,
示例:

輸入: ["eat", "tea", "tan", "ate", "nat", "bat"]
輸出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

說明:
所有輸入均為小寫字母,
不考慮答案輸出的順序,

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/group-anagrams
著作權歸領扣網路所有,商業轉載請聯系官方授權,非商業轉載請注明出處,

我的解法:

vector<vector<string>> groupAnagrams(vector<string>& strs) 
{
    vector<vector<string>> res;
    map<string,vector<string>> vec;
    if(strs.empty()) return res;
    for(int i=0;i<strs.size();i++)
    {
        string temp=strs[i];
        sort(temp.begin(),temp.end());
        vec[temp].push_back(strs[i]);
    }
    map<string,vector<string>>::iterator it;
    for(auto it=vec.begin();it!=vec.end();it++)
    {
        res.push_back(it->second);
    }
    return res;
}

思路:
在這里插入圖片描述
自己試一題:
給定一個字串,請你找出其中不含有重復字符的 最長子串 的長度,

示例 1:

輸入: "abcabcbb"
輸出: 3 
解釋: 因為無重復字符的最長子串是 "abc",所以其長度為 3

示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 因為無重復字符的最長子串是 "b",所以其長度為 1

示例 3:

輸入: "pwwkew"
輸出: 3
解釋: 因為無重復字符的最長子串是 "wke",所以其長度為 3,
     請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串,

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作權歸領扣網路所有,商業轉載請聯系官方授權,非商業轉載請注明出處,


結語

本來說呢,要把鏈表相關部分、堆疊相關部分也放進來,但是沒想到一個陣列講了這么多,
那就,下次吧,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/238113.html

標籤:其他

上一篇:【上岸經驗】粉絲僅作業2年就一個秋招拿了阿里,位元組跳動,騰訊的offer!(附上大佬的面經希望幫助到大家)

下一篇:csapp bomblab1—6+secret,較為全面,每個人的題不一樣。

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more