面試真題
真題1
#include <iostream>
// 在函數 find_repetnum 的參數列表中,int& length 中的 & 符號表示引用。通過將 length 聲明為引用,函數可以修改傳入的 length 變量的值,并且這種修改會在函數外部生效。
void find_repetnum(int* arr, int& length){int unique_index = 0;for (int i = 0; i < length - 1; i++) { // 修改循環條件if (arr[i] != arr[i + 1]) {arr[unique_index] = arr[i];unique_index++;}}arr[unique_index] = arr[length - 1]; // 處理最后一個元素length = unique_index + 1; // 更新數組長度
}int main(){int array[5] = { 1, 2, 2, 3, 4 };int length = 5;find_repetnum(array, length);for (int i = 0; i < length; i++) {std::cout << "Output Deal Data: " << array[i] << std::endl;}return 0;
}
真題2
第一步:實現快速排序
#include <iostream>
using namespace std;void quickSort(int arr[], int left, int right) {if (left < right) {int pivot = arr[(left + right) / 2];int i = left, j = right;while (i <= j) {while (arr[i] < pivot)i++;while (arr[j] > pivot)j--;if (i <= j) {swap(arr[i], arr[j]);i++;j--;}}quickSort(arr, left, j);quickSort(arr, i, right);}}int main() {int arr[] = { 5, 2, 9, 1, 7, 6, 3 };int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1);for (int i = 0; i < n; i++) {cout << arr[i] << " ";}cout << endl;return 0;
}
第二步:將比較部分單獨封裝,并作為函數指針傳遞給快速排序算法
#include <iostream>
using namespace std;bool compare_value(int num1, int num2) {if (num1 < num2)return true;elsereturn false;
}void quickSort(int arr[], int left, int right, bool (*ptr)(int, int)) {if (left < right) {int pivot = arr[(left + right) / 2];int i = left, j = right;while (i <= j) {while (ptr(arr[i], pivot))i++;while (ptr(pivot, arr[j]))j--;if (i <= j) {swap(arr[i], arr[j]);i++;j--;}}quickSort(arr, left, j, ptr);quickSort(arr, i, right, ptr);}}int main() {int arr[] = { 5, 2, 9, 1, 7, 6, 3 };int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1, compare_value);for (int i = 0; i < n; i++) {cout << arr[i] << " ";}cout << endl;return 0;
}
第三步:將第二步中的代碼,封裝成類模板
#include <iostream>
using namespace std;template <typename T>
class QuickSort {
public:bool compare_value(T num1, T num2) {if (num1 < num2)return true;elsereturn false;}void quickSort(T arr[], int left, int right, bool (*ptr)(T, T)) {if (left < right) {T pivot = arr[(left + right) / 2];int i = left, j = right;while (i <= j) {while (ptr(arr[i], pivot))i++;while (ptr(pivot, arr[j]))j--;if (i <= j) {swap(arr[i], arr[j]);i++;j--;}}quickSort(arr, left, j, ptr);quickSort(arr, i, right, ptr);}}
};int main() {int arr[] = { 5, 2, 9, 1, 7, 6, 3 };int n = sizeof(arr) / sizeof(arr[0]);QuickSort<int> qs;qs.quickSort(arr, 0, n - 1, qs.compare_value);for (int i = 0; i < n; i++) {cout << arr[i] << " ";}cout << endl;return 0;
}
注意:在類模板的sort函數中,需要將類模板的成員函數進行遞歸調用。因為sort函數是類模板QuickSort的成員函數,所以遞歸調用應該使用this->sort(arr, left, j)
;和this->sort(arr, i, right)
;。
知識點1:類模板
為什么需要類模板?
類模板與函數模板的定義和使用類似,有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同
類模板定義
類模板由模板說明和類說明構成模板說明同函數模板,如下:? template <類型形式參數表>
? 類聲明
template <typename Type>class ClassName{
public://ClassName 的成員函數
private:Type DataMember;}
單個類模板的使用
#include <iostream>
using namespace std;template<typename T>
class A
{public:// 函數的參數列表使用虛擬類型A(T t = 0){this->t = t;}// 成員函數返回值使用虛擬類型T& getT(){return t;}private:// 成員變量使用虛擬類型T t;
};void printA(A<int>& a){cout << a.getT() <<endl;
}int main(void){// 1、模板類定義類對象,必須顯示指定類型// 2、模板中如果使用了構造函數,則遵守以前的類的構造函數的調用規則A<int> a(666);cout << a.getT()<<endl;// 模板類做為函數參數printA(a);system("pause");return 0;
}
繼承中類模板的使用
父類是一般類,子類是模板類
class A{public:A(int temp =0){this->temp = temp;}~A(){}private:int temp;
};template <typename T>
class B :public A{public:B(T t = 0):A(666){this->t = t;}~B(){}private:T t;
};
子類是一般類,父類是模板類
template <typename T>
class A{public:A(T t = 0){this->t = t;}~A(){}private:T t;
};class B:public A<int>{public://也可以不顯示指定,直接A(666)B(int temp = 0):A<int>(666){this->temp = temp;}~B(){}private:int temp;
};
父類和子類都是模板類
父類和子類都是模板類時,子類的虛擬的類型可以傳遞到父類中。
結論
子類從模板類繼承的時候,需要讓編譯器知道父類的數據類型具體是什么
1.父類一般類,子類是模板類, 和普通繼承的玩法類似
2.子類是一般類,父類是模板類,繼承時必須在子類里實例化父類的類型參數
3.父類和子類都時模板類時,子類的虛擬的類型可以傳遞到父類中
類模板 template 和 template區別
template 用于基礎數據類型, T可以是int char 等
template 用于復制數據類型,T :string ,類等
知識點2:c++中什么時候需要使用this
在 C++ 中,關鍵字 this 是一個指向當前對象的指針,它在類的成員函數中使用。
一般情況下,你需要使用 this 指針來區分類的成員變量與局部變量或參數同名的情況。
以下是一些常見情況下需要使用 this 指針的情況:
1、區分成員變量和局部變量:當成員變量與局部變量同名時,使用 this-> 來引用成員變量,以區分兩者。
class MyClass {
public:int a;void setA(int a) {this->a = a; // 使用 this 指針來訪問成員變量 a}
};
2、在成員函數中返回對象本身:有時候在類的成員函數中需要返回對象本身,這時可以使用 return *this; 來返回當前對象。
class MyClass {
public:MyClass& doSomething() {// 進行操作return *this; // 返回當前對象}
};
3、在類內部調用其他成員函數:在類的成員函數中調用其他成員函數時,可以使用 this-> 來顯式調用。
class MyClass {
public:void func1() {// 一些操作}void func2() {this->func1(); // 顯式調用 func1}
};
總的來說,使用 this 指針可以幫助在類的成員函數中準確地引用成員變量、返回對象本身或者在類內部進行成員函數的調用。