顺序表-排序

来源:互联网 发布:网络倾听者app 编辑:程序博客网 时间:2024/04/28 01:17
/*
交换排序法
冒泡排序 | 鸡尾酒排序 | 奇偶排序 | 梳排序 | 侏儒排序 | 快速排序 |臭皮匠算法 | Bogo排序

选择排序法
选择排序 | 堆排序 | Smooth排序 | 笛卡尔树排序 | 锦标赛排序 | 循环排序

插入排序法
插入排序 | 希尔排序 | 二叉查找树排序 | 图书馆排序 | Patience排序

归并排序法
归并排序 | 多相归并排序 | Strand排序

分布排序法
美国旗帜排序 | 珠排序 | 桶排序 | 爆炸排序 | 计数排序 | 鸽巢排序 | 相邻图排序 | 基数排序 | 闪电排序

混合排序法
Tim排序 | 内省排序 | Spread排序 | 反移排序 | J排序

其他
双调排序器 | Batcher归并网络 | 两两排序网络
*/

#include "stdafx.h"
#include <iostream>
/*线性表-顺序表*/
template<typename T>
class Sort
{
public:
Sort();
~Sort();

void Swap(T &a,T &b);
void printfSort(T sort[],const int num);

void BuddleSort(T sort[],const int num);

void CocktailSort(T sort[],const int num); 

void InsertSort(T sort[],const int num);

void ShellSort(T sort[],const int num);

void SelectSort(T sort[],const int num);

void QuikeSort(T sort[],const int start,const int end);

void MegreSort(T sort[],const int num);
void megresort(T sort[],int start,int end,T temp[]);
void megrearray(T sort[],int start,int mid,int end,T temp[]);

void MinHeapFixup(T sort[],const int i); 
void MinHeapFixdown(T sort[],const int i,const int n);
void MakeMinHeap(T sort[],const int n); 
void MinheapSort(T sort[],const int n);  
void MinHeapAddNumber(T sort[],const int n,const int nNum); 
void MinHeapDeleteNumber(T sort[],const int n);  
};

template<typename T>
Sort<T>::Sort()
{

}

template<typename T>
Sort<T>::~Sort()
{
}


template<typename T>
void Sort<T>::printfSort(T sort[],const int num)
{
std::cout<<"-----------------------------------------------------------------------"<<std::endl;
for (int i = 0; i < num ; i++)
{
std::cout<<sort[i]<<std::endl;
}
}

template<typename T>
void Sort<T>::Swap(T &a,T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}

/*
冒泡排序法:
排序法:交换排序法
是否稳定排序:是
时间复杂度:最差,平均都是O(N2).最好是O(N);
空间复杂度:1
原理:
1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
3.N=N-1,如果N不为0就重复前面二步,否则排序完成。
*/

template<typename T>
void Sort<T>::BuddleSort(T sort[],const int num)
{
bool flag = true;
int temp = num,sort_end;
while (flag)
{
sort_end = temp;
flag = false;
for (int i = 1; i < sort_end; i++)
{
if (sort[i-1]>sort[i])
{
Swap(sort[i-1],sort[i]);
temp = i;
flag = true;
}
}
}
}

/*
鸡尾酒排序法(双向冒泡排序)
排序法:交换排序法
是否稳定排序:是
时间复杂度:最差,平均O(N2);最好是O(N);
原理:
(1)先对数组从左到右进行冒泡排序(升序),则最大的元素去到最右端;
(2)再对数组从右到左进行冒泡排序(降序),则最小的元素去到最左端。以此类推,依次改变冒泡的方向,并不断缩小未排序元素的范围。
*/

template<typename T>
void Sort<T>::CocktailSort(T sort[],const int num)
{
int top = 0,bottom = num-1;
bool flag = true;
while (flag)
{
flag = false;

for (int i = top; i < bottom; i++)
{
if (sort[i]>sort[i+1])
{
Swap(sort[i],sort[i+1]);
flag = true;
}
}
--bottom;

for (int j = bottom; j > top; --j)
{
if (sort[j]<sort[j-1])
{
Swap(sort[j],sort[j-1]);
flag = true;
}
}
++top;
}
}

/*
直接插入排序。
排序法:插入排序法
是否稳定排序:是
时间复杂度:最差,平均是O(n2),最好是O(n)。
原理:将数组分为无序区和有序区两个区,然后不断将无序区的第一个元素按大小顺序插入到有序区中去,最终将所有无序区元素都移动到有序区完成排序。
要点:设立哨兵,作为临时存储和判断数组边界之用。
效率: 最佳效率O(n);最糟效率O(n2)与冒泡、选择相同,适用于排序小列表  若列表基本有序,则插入排序比冒泡、选择更有效率。 
*/

template<typename T>
void Sort<T>::InsertSort(T sort[],const int num)
{
T temp;
int i,j;
for (i = 1; i < num; i++)
{
temp = sort[i];
for (j = i-1; j>=0 && temp < sort[j]; --j)
{
sort[j+1] = sort[j];
}
sort[j+1] = temp;
}
}

/*
希尔排序
排序法:插入排序法
是否稳定排序:否
时间复杂度:O(nlogn)
空间复杂度:1
原理:又称增量缩小排序。先将序列按增量划分为元素个数相同的若干组,使用直接插入排序法进行排序,然后不断缩小增量直至为1,最后使用直接插入排序完成排序。
要点:增量的选择以及排序最终以1为增量进行排序结束。
*/

template<typename T>
void Sort<T>::ShellSort(T sort[],const int num)
{
int row,i,j; T temp;
for (row = num/2; row >0; row /= 2)
{
for (i = row; i < num; i+=row)
{
temp = sort[i];
for (j = i-row; j >=0 && temp<sort[j]; j-=row)
{
sort[j+row] = sort[j];
}
sort[j+row] = temp;
}
}
}

/* 
选择排序。 
排序法:
思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序 
放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。  
 */  

template<typename T>
void Sort<T>::SelectSort(T sort[],const int num)
{
int i,j,nMinIndex;
for (i = 0; i < num; i++)
{
nMinIndex = i;
for (j = i+1; j < num; j++)
{
if (sort[nMinIndex]>sort[j])
{
min = j;
}
}

if (nMinIndex != i)
{
Swap(sort[i], sort[nMinIndex]);
}
}
}

/*
快速排序
原理:不断寻找一个序列的中点,然后对中点左右的序列递归的进行排序,直至全部序列排序完成,使用了分治的思想。
要点:递归、分治
思想:选定一个枢纽元素,对待排序序列进行分割, 
分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再 对这两个分割好的子序列进行上述的过程。 
总结:平均效率O(nlogn),适用于排序大列表。  
此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能 导致O(n2)的最糟用例效率。若数基本有序,效率反而最差。
选项中间 值作为枢纽,效率是O(nlogn)。基于分治法。   
*/

template<typename T>
void Sort<T>::QuikeSort(T sort[],const int start,int end)
{
if(start<end)
{
int i = start; int j =end; T middle = sort[start];
while (i<j)
{
while (i<j && sort[j] >= middle)
{
--j;
}
if(i<j) sort[i++] = sort[j];
while (i<j && sort[i]<middle)
{
++i;
}
if (i<j) sort[j++] = sort[i];
}
sort[i] = middle;

QuikeSort(sort,start,i-1);
QuikeSort(sort,i+1,end);
}
}

/*
归并排序
原理:将原序列划分为有序的两个序列,然后利用归并算法进行合并,合并之后即为有序序列。
要点:归并、分治
归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。
因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。
归并排序算法是一种O(nlogn)的算法。它的最差,平均,最好时间都是O(nlogn)。但是它需要额外的存储空间,这在某些内存紧张的机器上会受到限制。
*/

template<typename T>
void Sort<T>::MegreSort(T sort[],const int num)
{
T *temp_array = new T[num]; 
if (temp_array == NULL)
{
return;
}

megresort(sort,0,num-1,temp_array);

delete []temp_array;
}

template<typename T>
void Sort<T>::megresort(T sort[],int start,int end,T temp[])
{
if (start < end)
{
int mid = (start + end)/2;
megresort(sort,start,mid,temp);
megresort(sort,mid+1,end,temp);
megrearray(sort,start,mid,end,temp);
}
}

template<typename T>
void Sort<T>::megrearray(T sort[],int start,int mid,int end,T temp[])
{
int i = start;  int j = mid;
int m = mid +1; int n = end; int k=0;

while (i<=j && m<=n)
{
if (sort[i]<sort[m])
{
temp[k++] = sort[i++];
}
else
{
temp[k++] = sort[m++];
}
}

while (i<=j)
{
temp[k++] = sort[i++];
}

while (m<=n)
{
temp[k++] = sort[m++];
}

for (int l = 0; l < k; l++)
{
sort[start+l] = temp[l];
}
}

/*
堆排序属于百万俱乐部的成员。它特别适合超大数据量(百万条记录以上)的排序。
因为它并不使用递归(因为超大数据量的递归可能会导致堆栈溢出),而且它的时间也是O(nlogn)。还有它并不需要大量的额外存储空间。
堆排序的思路是:
(1)将原始未排序的数据建成一个堆。
(2)建成堆以后,最大值在堆顶,也就是第0个元素,这时候将第零个元素和最后一个元素交换。
(3)这时候将从0到倒数第二个元素的所有数据当成一个新的序列,建一个新的堆,再次交换第一个和最后一个元素,依次类推,就可以将所有元素排序完毕。
*/

template<typename T>
void Sort<T>::MinheapSort(T sort[],const int n)  
{  
for (int i = n - 1; i >= 1; i--)  
{  
Swap(sort[i], sort[0]);  
MinHeapFixdown(sort, 0, i);  
}  
}  

//建立最小堆  
template<typename T>
void Sort<T>::MakeMinHeap(T sort[],const int n)  
{  
for (int i = n / 2 - 1; i >= 0; i--)  
MinHeapFixdown(sort, i, n);  

// 新加入i结点  其父结点为(i - 1) / 2  
template<typename T>
void Sort<T>::MinHeapFixup(T sort[],const int i)  
{  
int j, temp;  

temp = sort[i];  
j = (i - 1) / 2;      //父结点  
while (j >= 0 && i != 0)  
{  
if (sort[j] <= temp)  
break;  

sort[i] = sort[j];     //把较大的子结点往下移动,替换它的子结点  
i = j;  
j = (i - 1) / 2;  
}  
sort[i] = temp;  
}

//在最小堆中加入新的数据nNum  
template<typename T>
void Sort<T>::MinHeapAddNumber(T sort[],const int n,const int nNum)  
{  
sort[n] = nNum;  
MinHeapFixup(sort, n);  
}  

//  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2  
template<typename T>
void Sort<T>::MinHeapFixdown(T sort[],int i,const int n)  
{  
int j; T temp;  

temp = sort[i];  
j = 2 * i + 1;  
while (j < n)  
{  
if (j + 1 < n && sort[j + 1] < sort[j]) //在左右孩子中找最小的  
j++;  

if (sort[j] >= temp)  
break;  

sort[i] = sort[j];     //把较小的子结点往上移动,替换它的父结点  
i = j;  
j = 2 * i + 1;  
}  
sort[i] = temp;  
}  
//在最小堆中删除数  
template<typename T>
void Sort<T>::MinHeapDeleteNumber(T sort[],const int n)  
{  
Swap(sort[0], sort[n - 1]);  
MinHeapFixdown(sort, 0, n - 1);  
}  

class User
{
public:
char username[20];
int usercode;

friend std::ostream& operator<< (std::ostream &out ,User &user)
{
out<<"username:"<<"\t"<<user.username<<"\t"<<"usercode:"<<"\t"<<user.usercode;
return out;
}

friend int operator> (const User &a,const User &b)
{
return a.usercode > b.usercode;
}

friend int operator>= (const User &a,const User &b)
{
return a.usercode >= b.usercode;
}

friend int operator< (const User &a,const User &b)
{
return a.usercode < b.usercode;
}

friend int operator<= (const User &a,const User &b)
{
return a.usercode <= b.usercode;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
User user[] = {{"c",97},{"g",93},{"d",96},{"e",95},{"a",99},{"b",98},{"f",94}};
Sort<User> sort;
const int num = sizeof(user)/sizeof(User);

sort.printfSort(user,num);
sort.MakeMinHeap(user,num);
sort.MinheapSort(user,num);
sort.printfSort(user,num);
system("pause");
return 0;
}