数据结构排序算法

来源:互联网 发布:it cost 编辑:程序博客网 时间:2024/06/03 10:53

数据结构排序算法

排序:排序即排列顺序,把一组数据排列成有序的数据,或者把一组数据按照关键字排成有序的

排序的分类:

     (1)按照存储位置分为:内部排序(即在内存中)和外部排序(即内存调用磁盘)

     (2)按照算法或者逻辑分为:插入排序、选择排序、交换排序、归并排序和基数排序

     (3)按照排序结果分为:升序排序和降序排序

时间复杂度:某个事件的执行次数

空间复杂度:临时存储位的个数

稳定性:重复数据在排序前后的位置不发生变化为稳定,反之为不稳定


下面将简要介绍插入排序、选择排序、交换排序、归并排序和基数排序等排序算法

插入排序(直接插入排序和希尔排序)

直接插入排序:

      (1)把一个数组先划分成已排序的部分和未排序的部分

      (2)从未排序部分获取一个关键字作为待排序数

      (3)在已排序的部分中找到合适的位置插入这个数据

直接插入排序的时间复杂度为 O(n^2), 空间复杂度为 O(1), 该算法是稳定的排序算法

直接插入排序代码如下:

void insertSort(int arr[], int len){int i, j;for (i = 2; i < len; i++){arr[0] = arr[i];for (j = i - 1; arr[j] > arr[0]; j--){arr[j + 1] = arr[j];}arr[j + 1] = arr[0];}}


希尔排序:即在直接插入排序的基础上,增加一个增量组合

希尔排序的时间复杂度为 O(n^1.3) ~ O(n^1.5), 空间复杂度为 O(1), 该算法是不稳定的排序算法

希尔排序的代码如下:

void shell(int *arr, int arr_len,int dk){int i, j;int tmp;for (i = dk; i < arr_len; i++){tmp = arr[i];for (j = i - dk; j >= 0 && arr[j] > tmp; j = j - dk){arr[j + dk] = arr[j];}arr[j + dk] = tmp;}}void shellSort(int *arr, int arr_len, int *dka, int dka_len){for (int i = 0; i < dka_len; i++){shell(arr,arr_len,dka[i]);}}


选择排序(简单选择排序和堆排序)

简单选择排序(以升序为例):一趟排序中找到最小的数,二趟排序中找到剩下数列中最小的数

简单选择排序是一种不稳定的排序算法

简单选择排序的代码如下:

void SelectSort(int *arr, int len){int i, j;int min;int tmp;//O(n^2) O(1)for (int i = 0; i < len-1; i++){ min = i;for (j = i + 1; j < len; j++){if (arr[j] < arr[min]){min = j;}}tmp = arr[min];arr[min] = arr[i];arr[i] = tmp;}}

堆排序
堆包括大根堆和小根堆
       大根堆:父节点的数据大于子节点的数据 ——> 升序
       小根堆:父节点的数据小于子节点的数据 ——> 降序
堆排序的代码如下:(以升序为例)
void HeapAdjust(int *arr, int i, int len)//堆调整{int j;//j <= len   有左子树 for (j = 2 * i; j <= len; j = 2 * j){//j  左子树   j = len; //有左 没右  j = len//左右都有 //就j < len//j = len   有左 没右// j < len  左右都有 if (j < len && arr[j] < arr[j + 1]){j++;}if (arr[j] < arr[i])break;arr[0] = arr[i];arr[i] = arr[j];arr[j] = arr[0];i = j;}}void HeapSort(int *arr, int len)//堆排序{int tmp;for (int i = len / 2; i > 0; i--){//i  当前要调整的堆的父节点下标  len 有效长度HeapAdjust(arr,i,len);}for (int j = len; j > 0; j--){tmp = arr[1];arr[1] = arr[j];arr[j] = tmp;HeapAdjust(arr, 1, j-1);}}

交换排序(冒泡排序和快速排序)

冒泡排序代码如下:

void BubbleSort(int *arr, int len){int tmp;bool mark = false;for (int i = 0; i < len-1; i++){mark = false;for (int j = 0; j < len - 1 - i; j++){if (arr[j]>arr[j + 1]){tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;mark = true;}}printf("i = %d\n", i);if (!mark){break;}}}


快速排序(分治法):选一个基准数,小的数据放在这个数左边,大的数据放在这个数右边

快速排序的代码如下:

int partition(int *arr, int low, int high){int tmp = arr[low];while (low < high){while (low < high && arr[high] >= tmp) high--;arr[low] = arr[high];while (low < high && arr[low] <= tmp) low++;arr[high] = arr[low];}arr[low] = tmp;return low;}void QSort(int *arr, int low, int high){if (low < high){int boundKey = partition(arr,low, high);QSort(arr, low, boundKey - 1);QSort(arr, boundKey+1, high);}}void QuickSort(int *arr, int len){QSort(arr, 0, len - 1);}


归并排序

     (1)分:利用二分法划分数列成小组

     (2)合:小组按照二分法划分出的小组组合

归并排序的代码如下:

void Merge(int *arr, int *tmp, int startIndex, int midIndex, int endIndex){int i = startIndex;int j = midIndex + 1;int k = startIndex;while (i != midIndex + 1 && j != endIndex + 1){if (arr[i] > arr[j]){tmp[k++] = arr[j++];}else{tmp[k++] = arr[i++];}}while (i != midIndex + 1){tmp[k++] = arr[i++];}while (j != endIndex + 1){tmp[k++] = arr[j++];}for (int i = startIndex; i <= endIndex; i++){arr[i] = tmp[i];}}void MergeSort(int *arr, int *tmp, int startIndex, int endIndex){if (startIndex < endIndex){int midIndex = (startIndex + endIndex) / 2;MergeSort(arr, tmp, startIndex, midIndex);MergeSort(arr, tmp, midIndex + 1, endIndex);Merge(arr, tmp, startIndex, midIndex, endIndex);}}


基数排序(排序趟数为最大值的位数)

基数排序的代码如下:

#define N 13//double pow(double,int);int FindMaxFinger(int *arr, int len)//计算最大值的位数{int max = arr[0];for (int i = 1; i < len; ++i){if (arr[i] > max){max = arr[i];}}int count = 0;while (max != 0){max = max / 10;count++;}return count;}//每个数据位的数 (45 0) 5  (45 1) 4//num/pow(10.0,fin)%10int FindFingerNumber(int num, int fin){return num / (int)pow(10.0,fin) % 10;}//0,1,2(个,十,百) 0不能参与排序void Radix(int *arr, int len, int fin){int tmp[10][N] = {};int num_fin;int count;for (int i = 0; i < len; i++){count = 0;num_fin = FindFingerNumber(arr[i], fin);//每个数据位的数while (tmp[num_fin][count] != 0){count++;}tmp[num_fin][count] = arr[i];}count = 0;for (int i = 0; i < 10; i++){for (int j = 0; j < len; j++){if (tmp[i][j] != 0){arr[count++] = tmp[i][j];}else{break;}}}}//0可以参与排序void Radix1(int *arr, int len, int fin){int tmp[10][N] = {};int num_fin;int count[10] = {};for (int i = 0; i < len; i++){num_fin = FindFingerNumber(arr[i], fin);tmp[num_fin][count[num_fin]] = arr[i];count[num_fin]++;}int index = 0;for (int i = 0; i < 10; i++){for (int j = 0; j < count[i]; j++){arr[index++] = tmp[i][j];}}}//每趟循环调用Radix()void RadixSort(int *arr, int len){int maxFinNum = FindMaxFinger(arr, len);for (int i = 0; i < maxFinNum; i++){Radix1(arr, len, i);}}


以上算法的时间复杂度、空间复杂度以及稳定性如下表显示:




原创粉丝点击