转自:http://blog.csdn.net/caryaliu/article/details/8280647
从以下几个方面来比较排序算法:
1. 算法的时间和空间复杂度
2. 排序的稳定性
3. 算法结构的复杂度
4. 参加排序的数据规模
排序的稳定性:
稳定排序方法:
插入排序、冒泡排序、二路归并排序、基数排序是稳定排序算法;
不稳定排序方法:
选择排序、谢尔排序、快速排序、堆积排序是不稳定排序算法。
算法复杂度比较:
各种内排序算法的时间、空间复杂度
排序方法 |
平均时间 |
最坏情况 |
辅助空间 |
插入排序 |
O(n*n) |
O(n*n) |
O(1) |
谢尔排序 |
O(n*log2n) |
O(n*log2n) |
O(1) |
泡排序 |
O(n*n) |
O(n*n) |
O(1) |
快速排序 |
O(n*log2n) |
O(n*n) |
O(log2n) |
选择排序 |
O(n*n) |
O(n*n) |
O(1) |
堆积排序 |
O(n*log2n) |
O(n*log2n) |
O(1) |
归并排序 |
O(n*log2n) |
O(n*log2n) |
O(n) |
基数排序 |
O(d*(n+r)) |
O(d*(n+r)) |
O(n+r) |
有结论如下:
1.
平均情况下,谢尔排序、快速排序、堆积排序、归并排序都能达到较快的排序速度,快速排序最快,堆积排序空间消费最省。
2.
平均情况下,插入排序和泡排序的排序速度较慢,但当参加排序的序列开始就局部有序时,这两种排序算法就能够达到较快的排序速度。最后情况下速度为O(n), 比情况 1
中叙述的4中方法都好,辅助空间消费也少。所以当 n 较小或者序列开始就局部有序时,可选择这两种方法。
3.
基数排序方法消费的辅助空间较多,但其时间复杂度可简化为O(dn); 当元素的位数较少时,可继续简化为O(n),
这种情况下也能达到较快的排序速度,另外,归并排序需要的辅助空间也较多。
4.
从算法结构的简单性来看,插入排序、泡排序、选择排序比较简单和直接;而谢尔排序、快速排序、堆积排序以及归并排序都可以看做对某一种排序算法的进一步改进,相对而言,改进后的算法都比较复杂。
5.
从参加排序的数据序列的规模大小来看,n越小,采用简单排序方法就越合适;n越大,采用改进的排序方法越合适。这是因为n越小,n*n 与 log2n
的差距越小。
以下是在考虑内排序算法的优缺点后,在某些情况下比较适合的算法选择:
1.
当参加排序的数据规模较大,关键字元素分布比较随机,并且不要求排序稳定性时,宜采用快速排序法。
2.
当参加排序的数据规模较大,内存空间又允许,并且有排序稳定性要求,宜采用归并排序法。
3.
当参加排序的数据规模较大,元素分布可能出现升序或者逆序的情况,并且对排序的稳定性无要求时,宜采用插入排序方法。
4.
当参加排序的数据规模较小(如小于100),元素基本有序(升序),或者分布也比较随机,并且有排序稳定性要求时,宜采用插入排序方法。
5.
当参加排序的数据规模n较小,对排序稳定性又不要求时,宜采用选择排序。
插入排序、选择排序、归并排序都比较容易在链表上实现,当利用链表作为存储结构时,可以避免将大量时间花费在元素的位置移动上。
算法描述:
1. 插入排序:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- void simple_insert(int *data, int len)
- {
- if(data == NULL || len < 1)
- return;
-
- int temp, i, j;
- for(i = 1; i < len; ++i) {
- temp = data[i];
- j = i - 1;
- while(j >= 0 && temp < data[j]) {
- data[j+1] = data[j--];
- }
- data[j+1] = temp;
- }
- }
-
-
-
-
-
-
-
- void binary_insert(int *data, int len)
- {
- if(data == NULL || len < 1)
- return;
-
- int temp, i, j, low, mid, high;
- for(i = 1; i < len; ++i) {
- temp = data[i];
- low = 0;
- high = i - 1;
- while(low <= high) {
- mid = (low + high)/2;
- if(temp < data[mid])
- high = mid - 1;
- else
- low = mid + 1;
- }
-
- for(j = i; j > low; --j)
- data[j] = data[j-1];
-
- data[low] = temp;
- }
- }
2. 谢尔排序
-
-
-
-
-
-
- void shellSort(int *data, int len)
- {
- if(data == NULL || len < 1)
- return;
-
- unsigned int gap = len;
- int i,j,temp;
- while(gap > 0) {
- gap >>= 1;
- for(i = gap; i < len; ++i) {
- j = i - gap;
- temp = data[i];
- while(j >= 0 && temp < data[j]) {
- data[j+gap] = data[j];
- j -= gap;
- }
-
- data[j+gap] = temp;
- }
- }
- }
3. 泡排序
-
-
-
-
-
-
-
-
-
-
- void bubbleSort(int *data, int len)
- {
- if(data == NULL || len < 1)
- return;
-
- int flag = 1;
- int i, j, temp;
- i = len - 1;
- while(i > 0 && flag == 1) {
- flag = 0;
- for(j = 0; j < i; ++j) {
- if(data[j] > data[j+1]) {
- temp = data[j];
- data[j] = data[j+1];
- data[j+1] = temp;
-
- flag = 1;
- }
- }
-
- --i;
- }
- }
4. 快速排序
-
-
-
- int randomInRange(int start, int end)
- {
- srand(time(NULL));
-
- return start + rand()%(end-start+1);
- }
-
-
-
-
- void swapElem(int *elem1, int *elem2)
- {
- int temp = *elem1;
- *elem1 = *elem2;
- *elem2 = temp;
- }
-
-
-
-
-
-
- int partition(int *data, int len, int start, int end)
- {
- if(data == NULL || len < 1 || start < 0 || end >= len) {
- printf("invalid parameters.");
- exit(1);
- }
-
- int index = randomInRange(start, end);
- swapElem(&data[index], &data[end]);
- int small = start - 1;
-
- for(index = start; index < end; ++index) {
- if(data[index] < data[end]) {
- ++small;
- if(small != index)
- swapElem(&data[index], &data[small]);
- }
- }
- swapElem(&data[++small], &data[end]);
-
- return small;
- }
-
-
-
-
-
-
-
-
-
- void quickSort(int *data, int len, int start, int end)
- {
- if(start == end)
- return;
-
- int index = partition(data, len, start, end);
- if(index > start)
- quickSort(data, len, start, index - 1);
- if(index < end)
- quickSort(data, len, index + 1, end);
- }
5. 选择排序
-
-
-
-
-
-
-
-
- void selectSort(int *data, int len)
- {
- if(data == NULL || len < 1)
- return;
-
- int i, j, minIndex;
- for(i = 0; i < len - 1; ++i) {
- minIndex = i;
- j = i + 1;
- while(j < len) {
- if(data[j] < data[minIndex])
- minIndex = j;
- ++j;
- }
-
- if(minIndex != i) {
- int temp = data[i];
- data[i] = data[minIndex];
- data[minIndex] = temp;
- }
- }
- }
6. 堆积排序
-
-
-
-
-
-
- void adjust(int *data, int len, int root)
- {
- int temp = data[root];
- int i = root * 2;
-
- while(i <= len) {
- if(i < len && data[i] < data[i + 1])
- ++i;
-
- if(temp >= data[i])
- break;
-
- data[i/2] = data[i];
- i *= 2;
- }
-
- data[i/2] = temp;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- void heapSort(int *data, int len)
- {
- if(data == NULL || len < 1)
- return;
-
- int i;
- for(i = len/2; i > 0; --i) {
- adjust(data, len, i);
- }
-
- int temp;
- for(i = len; i > 1; --i) {
- temp = data[1];
- data[1] = data[i];
- data[i] = temp;
-
- adjust(data, i-1, 1);
- }
- }
7. 归并排序
-
-
-
-
- void merge(int *source, int *des, int start, int mid, int end)
- {
- int i = start;
- int j = mid + 1;
- int k = start;
-
- while(i <= mid && j <= end) {
-
-
-
-
- des[k++] = source[i] <= source[j] ? source[i++] : source[j++];
- }
-
- while(i <= mid)
- des[k++] = source[i++];
- while(j <= end)
- des[k++] = source[j++];
- }
-
-
-
-
-
-
-
-
-
-
-
-
- void mpass(int *source, int *des, int len, int t)
- {
- int i = 0;
- if(len - i >= 2*t) {
- merge(source, des, i, i + t - 1, i + 2 * t - 1);
- i += 2 * t;
- }
-
- if(len - i > t)
- merge(source, des, i, i + t - 1, len - 1);
- else {
- for(; i < len; ++i)
- des[i] = source[i];
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- int mergeSort(int *data, int *des, int len)
- {
- int flag = -1;
- if(data == NULL || len < 1)
- return flag;
-
- int t = 1;
- flag = 1;
- while(t < len) {
- mpass(data, des, len, t);
- flag = 0;
-
- t *= 2;
- if(t < len) {
- mpass(des, data, len, t);
- t *= 2;
- flag = 1;
- }
- }
-
- return flag;
- }
8. 基数排序
-
-
-
- typedef struct Node {
- int data;
- struct Node *next;
- }QLink;
-
-
-
-
- int maxDig(int *data, int len)
- {
- int maxd = 0;
- int maxCurD = 1;
-
- int base = 10;
- for(int i = 0; i < len; ++i) {
- maxCurD = 1;
- base = 10;
- while(data[i] >= base) {
- ++maxCurD;
- if(maxd < maxCurD)
- maxd = maxCurD;
- base *= 10;
- }
- }
-
- return maxd;
- }
-
-
-
-
- QLink* transferArrToQLink(int *data, int len)
- {
- if(data == NULL || len < 1)
- return NULL;
-
- QLink *head = NULL;
- QLink *rear = NULL;
-
- for(int i = 0; i < len; ++i) {
- QLink *cur = (QLink *)malloc(sizeof(QLink));
- cur->data = data[i];
- cur->next = NULL;
- if(head == NULL)
- head = cur;
- else
- rear->next = cur;
- rear = cur;
- }
-
- return head;
- }
-
-
-
-
- void freeQLink(QLink *phead)
- {
- QLink *toFree = NULL;
- while(phead != NULL) {
- toFree = phead;
- phead = phead->next;
- free(toFree);
- }
- }
-
-
-
-
-
- int getCurPlaceV(int num, int index)
- {
- int placeValue;
- int i = 0;
- while(i <= index) {
- placeValue = num%10;
- num /= 10;
- ++i;
- }
-
- return placeValue;
- }
-
-
-
-
- void radixSort(int *data, int len, int radix)
- {
- int maxd = maxDig(data, len);
- printf("maxd = %d\n", maxd);
- QLink *phead = transferArrToQLink(data, len);
-
- QLink *Front[radix], *End[radix];
- QLink *q, *rear;
- int i, j, curplaceV;
- for(i = 0; i < maxd; ++i) {
- printf("the %d times sort\n", i);
- for(j = 0; j < radix; ++j)
- Front[j] = End[j] = NULL;
-
- q = phead;
- while(q != NULL) {
- curplaceV = getCurPlaceV(q->data, i);
- if(Front[curplaceV] == NULL)
- Front[curplaceV] = q;
- else
- End[curplaceV]->next = q;
- End[curplaceV] = q;
-
- q = q->next;
- }
-
- j = 0;
- while(Front[j] == NULL)
- ++j;
-
- phead = Front[j];
- rear = End[j];
- ++j;
- for(; j < radix; ++j) {
- if(Front[j] != NULL) {
- rear->next = Front[j];
- rear = End[j];
- }
- }
- rear->next = NULL;
- }
-
- q = phead;
- i = 0;
- while(q != NULL) {
- data[i++] = q->data;
- q = q->next;
- }
-
- freeQLink(phead);
- phead = NULL;
- }
排序算法小结,布布扣,bubuko.com
排序算法小结
原文:http://www.cnblogs.com/heyonggang/p/3648837.html