1. 程式人生 > >資料結構之排序(未完,待續)

資料結構之排序(未完,待續)

//資料結構知識點總結
//插入排序
//主程式碼
#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), 優缺點:效率快,難理解。 穩定性:不穩定。