一、排序的稳定性。
假设ki=kj(i!=j),并且在排序前的系列中ki领先kj。如果排序后ki仍然领先去kj,则此排序方法是稳定的,反之则不稳定。
二、内排序和外排序
内排序在排序过程中,待排序的所有记录全部被放置在内存中。外排序是由于排序的记录个数太多,不能同时放在内存,整个过程要在内外存之间多次交换数据。我们主要研究内排序。
影响内排序性能的三个方面:
1、时间性能;
2、辅助空间;
3、算法的复杂度;
三、排序方法
1、冒泡排序:两两相邻记录的关键字比较,如果反序则交换,直到没有记录。
void Swap(int *x1, int *x2)
{
int temp = *x1;
*x1 = *x2;
*x2 = temp;
}
void printArr(int *arr, int length)
{
for (int i = 0; i < length; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
///冒泡排序
///冒牌排序的初阶---简单易懂,效率低
void BubbleSort0(int *arr, int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i; j < length; j++)
{
if (arr[i] > arr[j])
{
Swap(&arr[i], &arr[j]);
}
}
}
}
///正宗的冒泡排序
void BubbleSort1(int *arr, int length)
{
for (int i = 0; i < length; i++)
{
for (int j = length - 1; j >= i; j--)
{
if (arr[j - 1] > arr[j])
{
Swap(&arr[j - 1], &arr[j]);
}
}
}
}
///冒泡排序的优化
void BubbleSort2(int *arr, int length)
{
//添加一个flag,初始值为false,如果产生了数据交换,就把它设为true,如果没有数据交换,说明此趟所有关键字已经排好序,退出循环
bool flag = true;
for (int i = 1; i < length&&flag; i++)
{
flag = false;
for (int j = length - 1; j >= i; j--)
{
if (arr[j - 1] > arr[j])
{
Swap(&arr[j - 1], &arr[j]);
flag = true;
}
}
}
}
冒泡排序的时间复杂度,最好是O(n),最差是;
2、简单选择排序
就是通过n-1次关键字的比较,从n-i+1个记录中选出最小的记录,并和第i个交换
///简单选择排序
void SelectSort(int *arr, int length)
{
int min;
for (int i = 0; i < length; i++)
{
min = i;
for (int j = i + 1; j < length; j++)
{
if (arr[min] > arr[j])
{
min = j;
}
}
if (i != min)
{
Swap(&arr[min], &arr[i]);
}
}
}
简单选择排序的时间复杂度为,但是简单选择排序的性能略优于冒泡排序。
3、直接插入排序
将一个记录插入到一个已经排好的有序表中,从而得到一个新的、记录数+1的有序表
///直接插入排序
void InsertSort(int *arr, int length)
{
int i, j;
for (i = 1; i < length; i++)
{
if (arr[i - 1] > arr[i])
{
int minner = arr[i];
for (j = i - 1; arr[j] > minner; j--)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = minner;
}
}
}
直接插入排序的时间复杂度为。
4、希尔排序
void shellsort(int *arr, int length)
{
int i;
int d = length / 2;
while (d > 0)
{
i = 0;
while (i < length && (i + d) < length)
{
if (arr[i] > arr[i + d])
{
Swap(&arr[i], &arr[i + d]);
}
i++;
}
d = d / 2;
}
}
希尔排序的时间复杂的,比直接插入排序好。
5、堆排序
void siftDown(int *arr, int length, int root)
{
int parent = root;
int child = parent * 2 + 1;
while (child < length)
{
if (child + 1 < length&&arr[child] > arr[child + 1])
child++;
if (arr[child] < arr[parent])
{
Swap(&arr[child], &arr[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//升序 建大堆
//降序 建小堆
void Heapsort(int *arr, int length)
{
assert(arr);
for (int i = (length - 2) / 2; i >= 0; i--)
{
siftDown(arr, length, i);
}
int end = length - 1;
while (end > 0)
{
Swap(&arr[0], &arr[end]);
siftDown(arr, end, 0);
--end;
}
}
void heapTopK(int *arr, int length, int k)
{
assert(arr);
int *heap = (int*)malloc(sizeof(int)*k);
for (int i = 0; i < k; i++)
{
heap[i] = arr[i];
}
for (int i = (k - 2) / 2; i >= 0; i--)
{
siftDown(heap, k, i);
}
for (int i = k; i < length; i++)
{
if (arr[i] > heap[0])
{
heap[0] = arr[i];
}
siftDown(heap, k, 0);
}
for (int i = 0; i < k; i++)
{
cout << heap[i] << ' ';
}
cout << endl;
}