计数排序
1、 名次 :所谓名次,通俗理解即为该元素在序列中排行老几的意思。
2.、如何求名次:依次对每一个元素进行比较,若排在自己(该元素)前面的元素比自己大,则前面的元素在排行计数上加1,反之则自己加1。
3、利用附加数组的计数排序:根据自身名次重新整理一份排序序列存储在附加数组中,然后将附加数组值拷贝到原序列中。
1)代码:
template<typename T> void SortClass<T>::rank(T a[], int n, int r[])
{
//给数组a[0: n-1]的n个元素排名次
//结果在r[0: n-1]中返回
for (int i = 0; i < n; i++)
r[i] = 0;
//比较所有元素,每次比较中较大元素计数器加1
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
if (a[j] <= a[i])
{
++r[i];
}
else
{
++r[j];
}
}//rank
template<typename T> void SortClass<T>::rearrange(T a[], int n)
{
T *u = new T[n]; //临时数组,存储排序元素
int *r = new int[n]; //存储数组元素名次
rank(a, n, r);
for (int i = 0; i < n; i++)
u[r[i]] = a[i];
for (int i = 0; i < n; i++)
a[i] = u[i];
delete [] u;
delete[] r;
}//rearrange
2)运行:
3)时间复杂度分析:在求名次rank()操作中,针对第i个元素,比较的次数为i次,因此总的比较次数为:1+2+3+…+(n-1)=(n-1)n/2次。在rearrange()中有2次for循环进行赋值操作,总的移动次数是2n。两者相加,得出附加数组的计数排序时间复杂度为:(n-1)n/2+2n =O(n2)(注:2为n的上标)
4、原地排序:所谓原地排序就是指在对序列元素进行名次计算之后,根据名次调整原序列的顺序,不借助附加数组。
1)思路:假设第一个元素a[0]的名次r[0]=3,那么,a[0]的值应该交换到下标为3的位置,即a[0]与a[3]交换。由于元素位置交换了,那么相应的,元素对应名次也要交换。停止交换的前提是a[0]元素对应的r[0]正好为0,则此时a[0]才是正确的元素。对其他位置元素,同理。
2 ) 代码:
template<typename T> void SortClass<T>::selfrearrange(T a[], int n)
{
int *r = new int[n]; //存储数组元素名次
rank(a, n, r);
for (int i = 0; i < n; i++)
while (i != r[i]) //当i == r[i]时,表明名次对应的下标存储元素正确
{
int tmp = r[i];
swap(a[i], a[tmp]); //元素交换
swap(r[i], r[tmp]); //排名交换
}
delete[] r;
}//selfrearrange
3)运行:
4)时间复杂度分析:名次比较次数:1+2+3+…+(n-1)=(n-1)n/2次。交换次数:当序列有序时,交换0次,当序列无序时,由于每次交换,至少使一个元素交换到正确位置,那么对任意一个元素而言,最多的交换次序是(n-1)次,在这(n-1)次交换中,其他元素也被交换正确,故最多的交换次数为(n-1)次。原地重排最坏的时间复杂度为:(n-1)n/2+(n-1)=O(n2)。
选择排序
1、定义:第一次遍历序列,找出最大元素,将该元素排到末尾去;第二次遍历序列,找出次最大元素,将该元素排到末尾前一位置去;同理,继续下去,直到最后一个元素为止。
2、思路:
3、基础选择排序:按照2中思路进行设计
1)代码:
template<typename T> void SortClass<T>::selectionSort(T a[], int n)
{
for (int i = n - 1; i > 0; i--) //移动的目标位置
{
int indexOfMax = 0;
for (int j = 0; j < i; j++) //找最大元素
if (a[indexOfMax] < a[j])
indexOfMax = j;
swap(a[i], a[indexOfMax]); //将最大值移到目标位置
}
}//selectionSort
2)运行:
3)时间复杂度分析:在进行查找最大元素值过程中,比较次数为(n-1)n/2。一次swap()操作,实际包含3步tmp=a;a=b;b=a;
,故移动次数为3(n-1)。基础选择排序的时间复杂度为(n-1)n/2+3(n-1)=O(n2)。
4、及时终止选择排序:在查找最大元素时,同时检查数组是否有序,减少不必要的迭代。
1)代码:
template<typename T> void SortClass<T>::selectionSortByOrder(T a[], int n)
{
bool sorted = false;
for (int i = n - 1; i > 0 && !sorted; i--) //未排好序的情况下进行选择排序
{
int indexOfMax = 0;
sorted = true;
for (int j = 0; j < i; j++)
if (a[indexOfMax] < a[j])
{
indexOfMax = j;
}
else
{
sorted = false;
}
swap(a[i], a[indexOfMax]);
}
}//selectionSortByOrder
2)运行:
冒泡排序
1、定义:简单来讲,相邻元素之间的比较,若前者较大,则交换。一轮比较即为一次冒泡过程。
2、基础冒泡排序:
1)代码:
template<typename T> void SortClass<T>::bubbleSort(T a[], int n)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < n - 1; j++)
if (a[j] > a[j + 1])
swap(a[j], a[j + 1]);
}//bubbleSort
2)运行:
3、及时终止的冒泡排序:
1)代码:
template<typename T> void SortClass<T>::bubbleSortByOrder(T a[], int n)
{
bool sorted = true;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1; j++)
if (a[j] > a[j + 1])
{
swap(a[j], a[j + 1]);
sorted = false; //只要交换顺序,表明排序未结束
}
if (sorted)
break;
}
}//bubbleSortByOrder
2)运行:
插入排序
1、定义: 把序列第一个元素看做一个有序数组,将第2个元素按顺序插入到这个数组中,则这两个数组组成一个新的有序数组。将第3个元素插入到上述有序数组中,那么这3个有序数组又组成新的有序数组。如此,依次将后续元素插入到前面已排好的序列中,直至最后一个元素为止。
2、将要插入元素与已知排序数组进行比较,从后往前逐一比较,若该元素较小,则将有序数组中元素后移一位,直到腾出可以插入的空位即可。
3、插入排序:
1)代码:
template<typename T> void SortClass<T>::insertSort(T a[], int n)
{
for (int i = 1; i < n; i++)
{
int j;
int tmp = a[i];
for (j = i - 1; j >= 0 && a[j] > tmp; j--) //将大于a[i]的元素依次后移
{
a[j + 1] = a[j];
}
a[j + 1] = tmp; //将a[i]元素按顺序插入到a[0:i-1]中
}
}//insertSort
2)运行:
附全代码:
#include<iostream>
using namespace std;
template <typename T> class SortClass
{
public:
void rank(T a[], int n, int r[]); //名次计算
void rearrange(T a[], int n); //利用附加数组计数排序
void selfrearrange(T a[], int n); //原地排序
void selectionSort(T a[], int n); //选择排序
void selectionSortByOrder(T a[], int n); //及时终止的选择排序
void bubbleSort(T a[], int n); //冒泡排序
void bubbleSortByOrder(T a[], int n); //及时终止的冒泡排序
void insertSort(T a[], int n); //插入排序
};
template<typename T> void SortClass<T>::rank(T a[], int n, int r[])
{
//给数组a[0: n-1]的n个元素排名次
//结果在r[0: n-1]中返回
for (int i = 0; i < n; i++)
r[i] = 0;
//比较所有元素,每次比较中较大元素计数器加1
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
if (a[j] <= a[i])
{
++r[i];
}
else
{
++r[j];
}
}//rank
template<typename T> void SortClass<T>::rearrange(T a[], int n)
{
T *u = new T[n]; //临时数组,存储排序元素
int *r = new int[n]; //存储数组元素名次
rank(a, n, r);
for (int i = 0; i < n; i++)
u[r[i]] = a[i];
for (int i = 0; i < n; i++)
a[i] = u[i];
delete [] u;
delete[] r;
}//rearrange
template<typename T> void SortClass<T>::selfrearrange(T a[], int n)
{
int *r = new int[n]; //存储数组元素名次
rank(a, n, r);
for (int i = 0; i < n; i++)
while (i != r[i]) //当i == r[i]时,表明名次对应的下标存储元素正确
{
int tmp = r[i];
swap(a[i], a[tmp]); //元素交换
swap(r[i], r[tmp]); //排名交换
}
delete[] r;
}//selfrearrange
template<typename T> void SortClass<T>::selectionSort(T a[], int n)
{
for (int i = n - 1; i > 0; i--) //移动的目标位置
{
int indexOfMax = 0;
for (int j = 0; j < i; j++) //找最大元素
if (a[indexOfMax] < a[j])
indexOfMax = j;
swap(a[i], a[indexOfMax]); //将最大值移到目标位置
}
}//selectionSort
template<typename T> void SortClass<T>::selectionSortByOrder(T a[], int n)
{
bool sorted = false;
for (int i = n - 1; i > 0 && !sorted; i--) //未排好序的情况下进行选择排序
{
int indexOfMax = 0;
sorted = true;
for (int j = 0; j < i; j++)
if (a[indexOfMax] < a[j])
{
indexOfMax = j;
}
else
{
sorted = false;
}
swap(a[i], a[indexOfMax]);
}
}//selectionSortByOrder
template<typename T> void SortClass<T>::bubbleSort(T a[], int n)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < n - 1; j++)
if (a[j] > a[j + 1])
swap(a[j], a[j + 1]);
}//bubbleSort
template<typename T> void SortClass<T>::bubbleSortByOrder(T a[], int n)
{
bool sorted = true;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1; j++)
if (a[j] > a[j + 1])
{
swap(a[j], a[j + 1]);
sorted = false; //只要交换顺序,表明排序未结束
}
if (sorted)
break;
}
}//bubbleSortByOrder
template<typename T> void SortClass<T>::insertSort(T a[], int n)
{
for (int i = 1; i < n; i++)
{
int j;
int tmp = a[i];
for (j = i - 1; j >= 0 && a[j] > tmp; j--) //将大于a[i]的元素依次后移
{
a[j + 1] = a[j];
}
a[j + 1] = tmp; //将a[i]元素按顺序插入到a[0:i-1]中
}
}//insertSort
int main(int argc, char *argv[])
{
int a[6] = { 6, 5, 8, 4, 3, 1 };
cout << "原始数组顺序: ";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;
SortClass<int> SClass;
/*SClass.rearrange(a, 6);
cout << "采用附加数组计数排序:";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;*/
/*SClass.selfrearrange(a, 6);
cout << "采用重排计数排序: ";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;*/
/*SClass.selectionSort(a, 6);
cout << "采用选择排序: ";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;*/
/*SClass.selectionSortByOrder(a, 6);
cout << "采用及时终止选择排序:";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;*/
/*SClass.bubbleSort(a, 6);
cout << "采用冒泡排序: ";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;*/
/*SClass.bubbleSortByOrder(a, 6);
cout << "采用及时终止冒泡排序:";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;*/
SClass.insertSort(a, 6);
cout << "采用插入排序: ";
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}