#include <iostream>
using namespace std;
extern int swap_count;
int swap_count = 0;
struct node
{
int i;
char c;
int operator > (node &a)
{
return (i > a.i);
}
int operator < (node &a)
{
return (i < a.i);
}
void operator = (node &a)
{
i = a.i;
c = a.c;
}
friend ostream &operator << (ostream &output, node &n)
//输入输出操作符只能重载为友元函数,其中operator前的 & 也是必不可少的,
{
output << n.i;
output << n.c;
return output;
}
};
template <typename T1>
void swap(T1 *a, T1 *b)
{
T1 c;
c = *a;
*a = *b;
*b = c;
swap_count += 1;
}
/**********************************
* 冒泡排序(BubbleSort),稳定排序,时间复杂度 N2 ,
* 逆序时性能最差,顺序时线性性能
*
***********************************/
template <typename T1>
void Bubble(T1 *pn, int len)
{
for(int i = len; i > 0; i--) //*******************
{
for(int m = 0; m < i; m++) //***************
{
if(*(pn + m) > *(pn + m + 1))
swap((pn+m), (pn+m+1));
}
}
}
/************************************
* 插入排序(InsertionSort),时间复杂度 N2 ,
* 稳定排序,逆序时性能最差,顺序时线性性能。
*
*************************************/
template <typename T1>
void Insertion(T1 *pn, int len)
{
T1 tmp;
for(int i = 0; i < len; i++)
{
tmp = *(pn+i);
for(int m = i +1; m < len; m++)
{
if(*(pn+m) < tmp)
swap(&tmp, (pn+m));
}
*(pn+i) = tmp;
}
}
/****************************************
* 希尔排序(ShellSort),时间复杂度 N1.25 ,
* 非稳定排序,对初始记录不敏感。
* 实质上是一种改进的插入排序:先将元素分成小组,插排,再合并,
* 再插排,最后合并成一组,而此时元素已经基本有序,
****************************************/
/* 程序员实用算法 里推荐的一种确定 h 值序列的方法:
* h1 = 1,n = 总元素个数,
* h(i+1) = 3h(i) + 1;当 h(x) > n/9 时停止,这种序列步进适合元素较多的时候,
***************************************/
//靠
template <typename T1>
void Shell(T1 *pn, int len)
{
for(int increment = len/2; increment > 0; increment /= 2)
{
for(int i = 0; i < len; i++) //虽然可行,但是会越界
{
T1 tmp;
tmp = *(pn+i);
for(int m = i + increment; m < len; m += increment)
{
if( *(pn+m) < tmp)
swap(&tmp, (pn+m));
}
*(pn+i) = tmp;
}
}
}
/******************************************
* 快速排序(QuickSort),使用很广泛的一种排序,性能比较好,实现略复杂点,
* 时间复杂度 N*logN 。选择一个基准,将数据集分成两个区:大于基准和小于基准的,
* 等于基准的随便放,然后对这两个区递归 , 不稳定排序
* 快排的缺点就是对于基本有序序列,效率反而很低,类似插排了,
******************************************/
template <typename T1>
void Quick(T1 *pn, int left, int right)
{
if(left < right)
{
int i = left;
int j = right;
while(1)
{
while(*(pn+(++i)) < *(pn+left));
while(*(pn+(--j)) > *(pn+left));
if(i>=j)
break;
swap(pn+i, pn+j);
}
//当这个循环结束时,i = j+1 必然成立 ??貌似
swap(pn+left, pn+j);
Quick(pn, left, j);
Quick(pn, i, right);
}
}
/***********************************************
* 堆排序(HeapSort),时间复杂度 N*logN ,比快速排序略慢,
* 但是不存在最坏情况,也是不稳定的排序
***********************************************/
//Heap_adjust:堆调整,大根堆
//这个差不多了,
//开始的错误是在于:调整成了一个近似于堆的东西,虽然最大值在最上面,但是后续的调整反而更麻烦
//不如开始时调整成标准的堆,这样后面的调整就可以局限在一定范围内
template <typename T1>
void Heap_adjust(T1 *pn, int i, int len)
{
int lc, rc, largest;
lc = 2*i + 1;
rc = 2*i +2;
largest = (lc < len && pn[lc] > pn[i]) ? lc : i;
largest = (rc < len && pn[rc] > pn[largest]) ? rc : largest;
if(largest != i)
{
swap(pn +i, pn +largest);
Heap_adjust(pn, largest, len);
}
}
template <typename T1>
void Heap(T1 *pn, int len)
{
for(int i = (len - 1)/2; i >= 0; --i)
Heap_adjust(pn, i, len);
//建立一个标准的大根堆,这样以后调整的时候方便,
//如果是近似大根堆,想以前的版本那样,以后调整反而得不偿失
int tmp = len;
for(int i = 0; i < len - 1; i++) //最后只剩一个节点时,没必要再调用函数调整了,
{
tmp -= 1;
swap(pn, pn + tmp);
Heap_adjust(pn, 0, tmp);
}
}
记录一下