1、【冒泡排序法】
又称交换排序法,即在排序过程中,让较大的元素向下沉,较小的元素向上浮,其处理程序从元素的开始位置起,相邻的元素进行比较,若第i个数大于第i+1个数,则互相交换,比较过所有的元素后,最大的元素将会被排到最后面;重复每一趟均会将最大值放在当前的最后面。
void bubble_sort(int* a,int sz) //常规发
{
int i = 0;
int j = sz;
while (j)
{
for (i=0; i<j-1; i++)
{
if (a[i] > a[i+1])
{
swap(a[i],a[i+1]);
}
}
j--;
}
}
由常规算法可发现有大量重复操作;
优化方法:
//冒泡排序---优化一-----设标志位
void Bubble1(int* array, int arrayLength) //标志
{
int i, j;
bool flag = true;
for (i = 0; i < arrayLength - 1 && flag; ++i)
{
flag = false;
for (j = 1; j < arrayLength - i; ++j)
{
if (array[j] < array[j - 1])
{
swap(array[j], array[j - 1]);
flag = true; //有交换,表明当前序列尚未有序,标志为ture
}
}
}
}
//冒泡排序优化二--------》只对无序的进行优化
void Bubble2(int* array, int arrayLength)
{
int flag = arrayLength - 1;
while (flag > 0)
{
for (int i = 0; i < arrayLength - 1; i++)
{
int k = flag;
flag = 0;
for (int j = 0; j < k; ++j)
{
if (array[j] < array[j + 1])
{
swap(array[j], array[j + 1]);
flag = j; //记录无序区的末尾位置
}
}
}
}
}
2、【直接插入排序】
思想:反复的插入新元素到已经排好的列表中
步骤:
a)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
b)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。
例如排序:67,33,21,84,49,50,75此7个数的过程:
void InsertSort(int* a, int sz)
{
int i = 0;
int j = 0;
for (i = 1; i < sz; i++)
{
int j = i - 1; //j以前为有序
int tmp = a[i];
while (j>=0 && a[j] > tmp)
{
a[j + 1] = a[j]; //逐个向后移动
j--;
}
a[j + 1] = tmp;
}
}
3、【希尔排序】
希尔排序实在插入排序的基础上发展而来的;
希尔排序也称之为递减增量排序,他是对插入排序的改进。在第二部插入排序中,我们知道,插入排序对于近似已排好序的序列来说,效率很高,可以达到线性排序的效率。但是插入排序效率也是比较低的,他一次只能将数据向前移一位。比如如果一个长度为N的序列,最小的元素如果恰巧在末尾,那么使用插入排序仍需一步一步的向前移动和比较,要N-1次比较和交换。
希尔排序通过将待比较的元素划分为几个区域来提升插入排序的效率。这样可以让元素可以一次性的朝最终位置迈进一大步,然后算法再取越来越小的步长进行排序,最后一步就是步长为1的普通的插入排序的,但是这个时候,整个序列已经是近似排好序的,所以效率高。
简言之,就是不断缩短步长进行插入排序,直到步长为0时排序结束。
void Shell_Sort(int* a,int sz)
{
int div = sz/2;
while (div > 0)
{
for (int i=0; i<sz; i+=div)
{
int j = i+div;
while (a[i]>a[j] && j<sz)
{
swap(a[i],a[j]);
j+=div;
}
}
div = div/2;
}
}
4、【快速排序】
算法思想:从待排序序列中选取一个值key,然后将小于key的数据全放在前面,大于key的数据全都放在后面,结果就是将序列分割成两个序列,不断进行如此分割,直到字表长度为不超过1时为止,此时有序。
int part1(int* a,int left,int right) //采用挖坑法
{
int key = a[right];
while (left<right)
{
while (left<right && a[left]<=key)
{
++left;
}
if (left<right)
{
a[right--] = a[left];
}
while (left<right && a[right]>= key)
{
--right;
}
if (left<right)
{
a[left++] = a[right];
}
}
a[left] = key;
return left;
}
void QuickSort(int* a, int left, int right)
{
if (left < right)
{
int div = part1(a,left,right);
QuickSort(a,left,div-1);
QuickSort(a,div+1,right);
}
}
5、【直接选择排序】每一次从待排的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
void SelectSort(int*a, int sz)
{
for (int i=0; i<sz; i++)
{
int key = i;
for (int j=i+1; j<sz; j++ )
{
if (a[key]>a[j])
{
key = j;
}
}
swap(a[i],a[key]);
}
}
6、【堆排序】
template <class T>
struct Less
{
bool operator()(const T& x1, const T& x2)
{
return x1 < x2;
}
};
//当需要大堆时
template <class T>
struct Greater
{
bool operator ()(const T& a, const T& b)
{
return a > b;
}
};
template<class T, class compare = Greater<T>>
class Heap
{
public:
Heap()
{}
Heap(T* array, size_t sz) //大堆
{
for (size_t i = 0; i < sz;++i)
{
_array.push_back(array[i]);
}
for (int j = (_array.size()-1) / 2; j>=0; --j)
{
_Adjustdown(j);
}
}
void Pop()
{
assert(!_array.empty());
swap(_array[0], _array[_array.size() - 1]);
_array.pop_back();
_Adjustdown(0);
}
void Push(const T& x)
{
_array.push_back(x);
_Adjustdown(0);
}
protected:
void _Adjustdown(int root) //向下调整算法
{
size_t parent = root;
size_t child = parent * 2 + 1;
while (parent <_array.size())
{
if ((child + 1)<(_array.size()) &&(_array[child + 1] > _array[child]))
{
++child;
}
if ((child<_array.size())&& (_array[child] > _array[parent]))
{
swap(_array[child], _array[parent]);
parent = child; //继续向下调整
child = parent * 2 + 1;
}
else
{
break;
}
}
}
private:
vector<T> _array;
};
7、【归并排序】
将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。
void
Merge
(
int
*
a
,
int
low
,
int
mid
,
int
high
)
//合并
{
int
i
=
low
;
int
left
=
low
;
int
j
=
mid
+ 1;
int
p
=
low
;;
int
*
tmp
= (
int
*)
malloc
((
high
-
low
+ 1)*
sizeof
(
int
));
//R1是局部向量
while
(
i
<=
mid
&&
j
<=
high
)
//两子文件非空时取其小者输出到R1[p]上
{
if
(
a
[
i
] <=
a
[
j
])
{
tmp
[
left
++] =
a
[
i
++];
}
else
{
tmp
[
left
++] =
a
[
j
++];
}
}
while
(
i
<=
mid
)
//若第1个子文件非空,则复制剩余记录到R1中
{
tmp
[
left
++] =
a
[
i
++];
}
while
(
j
<=
high
)
//若第2个子文件非空,则复制剩余记录到R1中
{
tmp
[
left
++] =
a
[
j
++];
}
while
(
p
<
left
)
{
a
[
p
++] =
tmp
[
p
];
//归并完成后将结果复制回R[low..high]
}
}
void
MergeSort
(
int
*
a
,
int
low
,
int
high
)
{
if
(
low
<
high
)
{
//int mid=(low+high)/2;
int
mid
=
low
+ (
high
-
low
) / 2;
MergeSort
(
a
,
low
,
mid
);
//递归地对R[low..mid]排序
MergeSort
(
a
,
mid
+ 1,
high
);
//递归地对R[mid+1..high]排序
Merge
(
a
,
low
,
mid
,
high
);
}
}