抽象类的介绍
抽象类是⼀种特殊的类,它是为了抽象和设计的⽬的为建⽴的,它处于继承层次结构的较上层。
(1)抽象类的定义:称带有纯虚函数的类为抽象类。
(2)抽象类的作⽤:
抽象类的主要作⽤是将有关的操作作为结果接⼝组织在⼀个继承层次结构中,由它来为派⽣类提供⼀个公共的根,派⽣类将具体实现在其基
类中作为接⼝的操作。所以派⽣类实际上刻画了⼀组⼦类的操作接⼝的通⽤语义,这些语义也传给⼦类,⼦类可以具体实现这些语义,也可
以再将这些语义传给⾃⼰的⼦类。
(3)使⽤抽象类时注意:
抽象类只能作为基类来使⽤,其纯虚函数的实现由派⽣类给出。如果派⽣类中没有重新定义纯虚函数,⽽只是继承基类的纯虚函数,
则这个派⽣类仍然还是⼀个抽象类。如果派⽣类中给出了基类纯虚函数的实现,则该派⽣类就不再是抽象类了,它是⼀个可以建⽴对
象的具体的类。
抽象类是不能定义对象的。
总结:
1. 纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数⼀定没有定义,纯虚函数⽤来规范派⽣类的⾏为,即接⼝。包含纯虚函数的类
是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引⽤。
2. 虚函数声明如下:virtual ReturnType FunctionName(Parameter);虚函数必须实现,如果不实现,编译器将报错,错误提⽰为:
error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"
3. 对于虚函数来说,⽗类和⼦类都有各⾃的版本。由多态⽅式调⽤的时候动态绑定。
4. 实现了纯虚函数的⼦类,该纯虚函数在⼦类中就编程了虚函数,⼦类的⼦类即孙⼦类可以覆盖该虚函数,由多态⽅式调⽤的时候动态
绑定。
5. 虚函数是C++中⽤于实现多态(polymorphism)的机制。核⼼理念就是通过基类访问派⽣类定义的函数。
6. 在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。
7. 友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调⽤虚拟成员函数来解决友元
的虚拟问题。
8. 析构函数应当是虚函数,将调⽤相应对象类型的析构函数,因此,如果指针指向的是⼦类对象,将调⽤⼦类的析构函数,然后⾃动调
⽤基类的析构函数。
有纯虚函数的类是抽象类,不能⽣成对象,只能派⽣。他派⽣的类的纯虚函数没有被改写,那么,它的派⽣类还是个抽象类。
定义纯虚函数就是为了让基类不可实例化化
因为实例化这样的抽象数据结构本⾝并没有意义。
或者给出实现也没有意义
实际上我个⼈认为纯虚函数的引⼊,是出于两个⽬的
1、为了安全,因为避免任何需要明确但是因为不⼩⼼⽽导致的未知的结果,提醒⼦类去做应做的实现。
2、为了效率,不是程序执⾏的效率,⽽是为了编码的效率。
链表和数组有什么区别 数组和链表有以下几点不同: (1) 存储形式:数组是一块连续的空间,声明时就要确定长度。链表是一块可不连续的动态空间,长度可变,每个结点要保存相邻结点指针。 (2) 数据查找:数组的线性查找速度快,查找操作直接使用偏移地址。链表需要按顺序检索结点,效率低。 (3) 数据插入或删除:链表可以快速插入和删除结点,而数组则可能需要大量数据移动。 (4) 越界问题:链表不存在越界问题,数组有越界问题。
链表反转
何避免“野指针” “野指针”产生原因及解决办法如下: (1) 指针变量声明时没有被初始化。解决办法:指针声明时初始化,可以是具体的地址值,也可让它指向 NULL。 (2) 指针 p 被 free 或者 delete 之后,没有置为 NULL。解决办法:指针指向的内存空间被释放后指针应该指向 NULL。 (3) 指针操作超越了变量的作用范围。解决办法:在变量的作用域结束前释放掉变量的地址空间并且让指针指向 NULL。 注意:“野指针”的解决方法也是编程规范的基本原则,平时使用指针时一定要避免产生“野指针”,在使用指针前一定要检验指针的合法性。
代码反转
反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *next, *prev = nullptr;
ListNode *curr = head;
while(curr != nullptr) {
next = curr ->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};
数组里面最大三个数的乘积
int number[10] = { 1,2,9,7,-1,-5,-7,7,1 };
sort(number, number +10, greater<int>()); //大到小
//sort(number, number + 10, less<int>()); //小到大
解开 最大的三个数字 或者 最大*两个最小的
这道题包含三种情况,要找的这三个数全是正数,全是负数,有正有负,全是正数和全是负数都只需要最大的三个数相乘,所得的乘积就是最大的,有正有负的情况下只有两个数是负数的情况才会对乘积最大有贡献,所以我们只需要找出最大的三个数和最小的三个数,然后比较三个正数的乘积和最大正数和最小两个负数的乘积即可
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
long long a[n];
long long b,c;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
b=a[0]*a[1]*a[n-1];
c=a[n-1]*a[n-2]*a[n-3];
if(b>c){
cout<<b<<endl;
}else {
cout << c << endl;
}
return 0;
}
X的平方根
牛顿迭代
二分法
class Solution {
public:
int mySqrt(int x) {
int index = -1,left = 0, right = x;
while (left <= right) {
int mid = left + (right - left) / 2;
if ((long long)mid * mid <= x) {
index = mid;
left = mid + 1;
}
else {
right = mid - 1;
}
}
return index;
}
};
// x平方 = n X = (x + n/x) /2 复杂度O(n)
class Solution {
public:
int mySqrt(int x) {
if( x == 0) {
return x;
}
double nn = x, nx = x, nmin;
while(true) {
nmin = (nx/nn + nn) /2;
if(fabs(nmin - nn) < 1e-7) {
break;
}
nn = nmin;
}
return int(nn);
}
};
给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。
示例 1:
输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
中心下标是 3 。
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
class Solution {
public:
int pivotIndex(vector<int> &nums) {
// int total = accumulate(nums.begin(), nums.end(), 0);
int total ;
for(auto ch:nums) {
total += ch;
}
// int sum = 0;
// for (int i = 0; i < nums.size(); ++i) {
// if (2 * sum + nums[i] == total) {
// return i;
// }
// sum += nums[i];
// }
int sum = 0;
for(int i = 0; i < nums.size(); i++) {
sum += nums[i];
if(total == sum) {
return i;
}
total -= nums[i];
}
return -1;
}
};
class Solution {
public:
int pivotIndex(vector<int> &nums) {
// int total = accumulate(nums.begin(), nums.end(), 0);
int total ;
for(auto ch:nums) {
total += ch;
}
int sum = 0;
for(int i = 0; i< nums.size(); i++) {
if(2*sum + nums[i] == total){
return i;
}
sum += nums[i];
}
return -1;
}
};