最快的排序:桶排序
查找:顺序查找(没排序);折半查找(已排序)
冒泡排序
void Sort(int* arr, int aLength)
{
for (int k = 0; k < aLength ; k++)
{
for (int i = 0; i < aLength - 1; i++)
{
if (arr[i] > arr[i + 1])
{
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
printf("%d", arr[k]);
}
}
需要排序的可能还有其它类型,比如double、float、short、结构、类等,不限于int;
这样导致需要给每一种类型都写一个相同的排序方法;
折半查找
顺序查找 ->从头开始一个个找,适合于没排序时查找;
例如:从一个数组{1,5,3,7,9}中找3的下标;从第一个数开始往后找,找到3后返回3的下标即可;
折半查找 ->前提条件是排好序,每次查找砍掉一半,可以提高查找效率;
例如: 从数组{1,3,5,7,9,11,13}中找出3的下标;
用数组长度/2得到下标;7/2=3;
找到下标处的数与目标数比较;第3个数是5,5>3说明3在5前面,于是5和它后面的部分不再考虑;依次类推找到目标数;
int Find(int* arr, int alength, int Element)
{
int nBegin = 0;
int nEnd = alength;
while (nBegin <= nEnd)
{
int Index = (nBegin + nEnd) >> 1;
if (arr[ Index] < Element)
{
nBegin = Index;
}
else if (arr[Index] > Element)
{
nEnd = Index;
}
else
{
return Index;
}
}
}
模版
上面的冒泡排序和折半查找只能适用于int型;
如果想适应于多种类型,可以使用模板;
模板的本质就是代码的复制;
编译时编译器将会模板替换成对应的类型;
使用模板和不使用模板的反汇编完全一样;
可以利用模板来实现链表结构;
函数中的类型不确定时可以用模板
例如:用模板修改后的冒泡排序和折半查找
#include"c++test.h"
template<typename T>
void Sort(T arr, int aLength)
{
for (int k = 0; k < aLength ; k++)
{
for (int i = 0; i < aLength - 1; i++)
{
if (arr[i] > arr[i + 1])
{
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
printf("%d", arr[k]);
}
}
template<class E,typename R>
int Find(E arr, int alength, R Element)
{
int nBegin = 0;
int nEnd = alength;
while (nBegin <= nEnd)
{
int Index = (nBegin + nEnd) >> 1;
if (arr[ Index] < Element)
{
nBegin = Index;
}
else if (arr[Index] > Element)
{
nEnd = Index;
}
else
{
return Index;
}
}
}
int main(int argc, char* argv[])
{
char arr[] = { 1,2,3,4,7 };
printf("%d", Find(arr, 5, 4));
}
在C++中,typename
和 class
在模板中用于定义模板类型参数,两者的作用是相同的,用法也非常类似。但是在某些情况下,它们的使用是有区别的。
通常情况下,使用 class
关键字和使用 typename
关键字定义模板类型参数是等效的。例如,下面两种方式都可以定义一个类型参数 T
:
template <typename T>
class MyClass {};
template <class T>
class MyClass {};
然而,当模板类型参数是一个依赖于模板参数的类型名时,需要使用 typename
。例如:
template <typename T>
class MyClass {
public:
typedef typename T::value_type value_type;
// ...
};
在上面的代码中,typename T::value_type
表示 T
类型中的一个类型名,而 typename
关键字告诉编译器这是一个类型名。如果没有 typename
关键字,编译器会将 T::value_type
解释为一个静态成员变量或者函数,从而导致编译错误。
因此,typename
关键字用于指示模板类型参数中的某个名称是一个类型名,而不是一个变量名或函数名。而 class
关键字只是一种语法上的替代方式。
在结构体和类中也可以使用模版
template<class T,class M>
struct Base
{
T x;
T y;
M a;
M b;
T Max()
{
if(x>y)
{
return x;
}
else
{
return y;
}
}
M Min()
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
};
int main(int argc, char* argv[])
{
Base<int,char> base;
base.x = 10;
base.y = 20;
base.a = 1;
base.b = 2;
int x = base.Max();
int y = base.Min();
printf("%d %d\n",x,y);
return 0;
}
练习
1.使用模版实现swap(x,y)
template<typename T>
void Swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
int main(int argc, char* argv[])
{
double x = 10;
double y = 20;
Swap(x, y);
printf("%d %d",x,y);
return 0;
}
2.利用模版实现冒泡排序(实际是为了引出运算符重载)
template<typename T,typename E>
void Sort(T* arr, E aLength)
{
int n = 0;
for (int k = 0; k < aLength; k++)
{
for (int i = 0; i < aLength - 1; i++)
{
if (arr[i] > arr[i + 1])
{
T temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
while (n < 2)
{
printf("%d", arr[n]);
n++;
}
}
class Student
{
public:
int x;
int y;
};
int main(int argc, char* argv[])
{
Student st,st1;
st.x = 10;
st.y = 20;
st1.x = 11;
st1.y = 21;
Student arr[] = { st,st1 };
Sort(arr, 2);
return 0;
}