資料結構之排序(未完,待續)
阿新 • • 發佈:2019-02-17
//資料結構知識點總結
//插入排序
//主程式碼
#include<stdio.h>
void InsertSort(int * a, size_t n)//直接插入排序
{
assert(a != NULL);
int end = 0;
for (int i = 0; i < n - 1; ++i)
{
end = i;
while (end >= 0)
{
if (a[end]>a[end + 1])
{
Swap(&a[end], &a[end + 1 ]);
end--;
}
else
{
break;
}
}
}
}
//希爾排序
void ShellSort(int *a, size_t n)//希爾排序
{
assert(a != NULL);
//預排序
int gap = n / 3 + 1;//希爾排序所需要的跨度
while (gap > 1)
{
for (int i = 0; i < n - gap; ++i)
{
int end = i;
while (end >= 0)
{
if (a[end]>a[end + gap])
{
Swap(&a[end], &a[end + gap]);
end -= gap;
}
else
{
break;
}
}
}
gap = gap / 3 + 1;
}
//直接插入排序
InsertSort(a, n);
}
//對比,直插排序:時間複雜度,最好情況O(n);最壞情況O(n^2),空間複雜度O(1)。
//希爾排序,時間複雜度大約在O(n^1.25)~O(1.6n^1.25) ,空間複雜度O(1)。
void SelectSort(int *a, size_t n)//選擇排序
{
assert(a != NULL);
for (int i = 0; i < n; i++)
{
int min = i;
for (int j = j + 1; j < n; j++)
{
if (a[min]>a[j])
{
min = j;
}
}
Swap(&a[min], &a[i]);
}
}
void SelectSort(int *a, size_t n)
{
assert(a != NULL);
int left = 0;
int right = n - 1;
while (left < right)
{
int min = left;
int max = left;
for (int i = left; i <= right; i++)
{
if (a[min]>a[i])
{
min = i;
}
if (a[max] < a[i])
{
max = i;
}
}
Swap(&a[left], &a[min]);
if (left != max)
{
Swap(&a[right], &a[max]);
}
left++;
right--;
}
}
//堆排序
//先將陣列建堆,如果要排升序,就鍵大堆,排降序,就建小堆
//建堆完畢後,用替換法進行排序
void AdjustDown(DataType* a, size_t n, int root)//建大堆
{
int parent = root;
int child = parent * 2 + 1;
while (child < n)
{
if ((child + 1) < n&&a[child] < a[child + 1])
{
child++;
}
if (a[parent] < a[child])
{
DataType tmp = a[parent];
a[parent] = a[child];
a[child] = tmp;
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void MakeHeap(DataType*a, size_t n)//建堆
{
int i = (n - 1) >> 1;
for (; i >= 0; --i)
{
AdjustDown(a, n, i);
}
}
void HeapSort(DataType* a, size_t n)
{
MakeHeap(a, n);
int end = n - 1;
while (end > 0)
{
DataType tmp = a[end];
a[end] = a[0];
a[0] = tmp;
AdjustDown(a, end, 0);
end--;
}
}
//選擇排序:時間複雜度O(n^2),空間複雜度O(1),堆排序:時間複雜度O(n*logn),空間複雜度O(1)
//快速排序
//快排的三種方法
int LeftRightPointer(int*a, int left, int right)//左右指標法
{
int begin = left;
int end = right;
int mid = Mid(a, left, right);
Swap(&a[mid], &a[right]);
int key = a[right];
while (begin < end)
{
while (begin < end&&a[begin] <= key)
{
begin++;
}
while (begin < end&&a[begin] <= key)
{
end--;
}
Swap(&a[begin], &a[end]);
}
Swap(&a[begin], &a[right]);
return begin;
}
void QuickSort(int* a, int left, int right)
{
assert(a != NULL);
if (left >= right)
{
return;
}
int div = LeftRightPointer(a, left, right);
QuickSort(a, left, div - 1);
QuickSort(a, div + 1, right);
}
//快排的優化,以左右指標法為例
int Mid(int* a, int left, int right)//三數取中法
{
int mid = left + ((right - left) >> 1);
if (a[left] > a[right])
{
if (a[left] < a[mid])
{
return left;
}
else if (a[right] < a[mid])
{
return mid;
}
else
{
return right;
}
}
else
{
if (a[right] < a[mid])
{
return right;
}
else if (a[left] < a[mid])
{
return mid;
}
else
{
return left;
}
}
}
int LeftRightPointer(int* a, int left, int right)//左右指標快排
{
int begin = left;
int end = right;
//選key的優化
int mid = Mid(a, left, right);
Swap(&a[mid], &a[right]);
int key = a[right];
while (begin < end)
{
while (begin < end&&a[begin] <= key)
{
begin++;
}
while (begin < end&&a[end] >= key)
{
end--;
}
Swap(&a[begin], &a[end]);
}
Swap(&a[begin], &a[right]);
return begin;
}
直接插入排序:時間複雜度:最好O(n),最壞 O(n^2),空間複雜度O(1),優缺點,越接近有序越快,穩定性:穩定。
選擇排序:時間複雜度:O(n^2),空間複雜度O(1),優缺點,效率最低,唯一的優點是直觀,穩定性:不穩定。
堆排序:時間複雜度O(n*logn),空間複雜度O(n),優缺點:所有排序方式中,整體而言最快。穩定性:不穩定。
氣泡排序:時間複雜度O(n^2),空間複雜度O(1),優缺點:效率不是很快。穩定性:穩定
快速排序:時間複雜度: 優化後O(n*logn),空間複雜度:遞迴:O(1),非遞迴O(n),
優缺點:效率快,難理解。
穩定性:不穩定。