C++编程面试复盘:数组降重+快排+函数指针+类模板

面试真题

真题1:数组降重

方法一:普通方法

#include <iostream>
void removeDuplicates(int array[], int& length) {
    int index = 0;
    for (int i = 0; i < length; i++) {// 开始遍历原始数组中的元素
        bool isDuplicate = false;
        for (int j = 0; j < index; j++) {// 对于每个元素 array[i],再次遍历去重后的数组(即前面已经处理过的部分),查找是否存在相同的元素。
                                       // 如果找到相同的元素,则跳出循环,不做任何操作。
            if (array[i] == array[j]) {
                isDuplicate = true;
                break;
            }
        }
        if (!isDuplicate) {
            array[index++] = array[i];
        }
    }
    length = index;
}

int main() {
    int array[5] = { 4, 2, 2, 1, 2 };
    int length = 5;

    std::cout << "原始数组:" << std::endl;
    for (int i = 0; i < length; i++) {
        std::cout << array[i] << " ";
    }
    std::cout << std::endl;

    removeDuplicates(array, length);

    std::cout << "去重后的数组:" << std::endl;
    for (int i = 0; i < length; i++) {
        std::cout << array[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

方法二:使用STL

#include <iostream>
#include <unordered_set>

int main() {
    int array[5] = { 4, 2, 2, 1, 2 };
    int length = 5;

    std::unordered_set<int> uniqueSet;
    
    for (int i = 0; i < length; i++) {
        uniqueSet.insert(array[i]);
    }

    std::cout << "去重后的数组:" << std::endl;
    for (int num : uniqueSet) {
        std::cout << num << " ";
    }
    
    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;
    else
        return 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--;
            }
        }
        // 此时,(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;
        else
            return 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 指针可以帮助在类的成员函数中准确地引用成员变量、返回对象本身或者在类内部进行成员函数的调用。

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值