排序:将一连串记录按照关键字的大小(从大到小或从小到大)进行排列。
稳定性:如果两个大小相同的关键字的相对位置在排序前和排序后是一样的(Ai等于Aj,排序前Ai 在Aj的前面,排序后Ai 还是在Aj的前面),那么这种算法就是稳定的。
稳定的排序算法有:冒泡排序、直接插入排序、归并排序、基数排序
不稳定的排序算法有:选择排序、快速排序、希尔排序、堆排序
冒泡排序:
每轮都是从第一个元素开始,按顺序比较相邻的2个元素,将大的元素放到后面,小的元素放到前面。这样经过第一轮后,最大的元素位于最后的位置。第二轮后第二大的元素将位于倒数第2的位置。经过N-1轮后,所有的元素都将按从小到大排列。
最好的时间复杂度为O(n),最坏的时间复杂度为O(n^2),平均时间复杂度为O(n^2)。
c++代码:
void BubbleSort(int iArr[], int iNum) { int i, j, iTemp; for (i = 0; i < iNum - 1; i++) //总共进行iNum-1轮 { for (j = 0; j < iNum - i - 1; j++) //每轮要比较的次数为iNum-i-1 { if (iArr[j] > iArr[j + 1]) //将大的元素往后放 { iTemp = iArr[j]; iArr[j] = iArr[j + 1]; iArr[j + 1] = iTemp; } } } }
直接插入排序:
每次从无序表中取出第一个元素,把它插入到有序表的适合位置,使有序表仍然有序。
平均时间复杂度为O(n^2)。
c++代码:
void InsertionSort(int iArr[], int iNum) { int i, j, iTemp; for (i = 1; i < iNum; i++) //总共进行iNum-1轮 { iTemp = iArr[i]; //将当前要插入的元素先备份 j = i - 1; //从要插入元素的前一个元素开始比较 while((j >= 0) && (iArr[j] > iTemp)) { //将比iTemp大的元素往后移一个位置 iArr[j + 1] = iArr[j]; j--; } //如果j不等于i-1,说明这一轮有元素移动 if (j != i - 1) { iArr[j + 1] = iTemp;//将要插入的元素放到适当的位置 } } }
归并排序:
假设有一个数列{2,0,1,6,3,8,7,4,5,9}
第一次归并后:{0,2},{1,6},{3,8}{4,7},{5,9}
第二次归并后:{0,1,2,6},{3,4,7,8},{5,9}
第三次归并后:{0,1,2,3,4,6,7,8},{5,9}
第四次归并后:{0,1,2,3,4,5,6,7,8,9}
平均时间复杂度为O(nlogn)。
基数排序:
先将元素按个位数大小进行排序,再将元素按十位数大小进行排序····
假设有一数列{73,22,93,43,55,14,28,65,39,81}
按个位数排序后:{81,22,73,93,43,14,55,65,28,39}
按十位数排序后:{14,22,28,39,43,55,65,73,81,93}
平均时间复杂度为O(n)。
c++代码:
void RadixSort(int iArr[], int iNum) { int iMax = iArr[0]; for (int i = 1; i < iNum; i++)//获取序列的最大元素 { if (iMax < iArr[i]) iMax = iArr[i]; } int iLoop = 0; while (iMax != 0)//计算最大元素的位数 { iLoop++; iMax /= 10; } int iRow; for (int i = 1; i <= iLoop; i++)//根据最大位数进行循环 { //iBackup的第一列用来存放对应行中存放的元素个数 int iBackup[10][20] = {0}; int iNumber = pow(10.0, i - 1); for (int j = 0; j < iNum; j++)//遍历所有元素 { //第一轮计算个位数,第二轮计算十位数??? iRow = (iArr[j] / iNumber) % 10; //将元素按照iRow的大小存放到iBackup对应的行中 int ilist = ++iBackup[iRow][0]; iBackup[iRow][ilist] = iArr[j]; } int k = 0; //按顺序将iBackup中的元素放回iArr数组中 for (int m = 0; m < 10; m++) { for (int n = 1; n <= iBackup[m][0]; n++) { iArr[k++] = iBackup[m][n]; } } } }选择排序:
每一次从待排序的元素中选出最小的一个元素,放在序列的起始位置。
平均时间复杂度为O(n^2)。
c++代码:
void SelectSort(int iArr[], int iNum) { for (int i = 0; i < iNum - 1; i++) //总共进行iNum-1轮 { int iMin = i;//iMin为本轮中最小元素的下标 for (int j = i + 1; j < iNum; j++)//查找本轮最小元素 { if (iArr[iMin] > iArr[j]) { iMin = j; } } if (iMin != i) { //将本轮最小元素放在序列开头 int iSwap = iArr[i]; iArr[i] = iArr[iMin]; iArr[iMin] = iSwap; } } }
快速排序:
通常选择序列的第一个元素为关键数据,将小于关键数据的元素放在关键数据前面,将大于关键数据的元素放在关键数据后面。然后再对关键数据前后两个序列做同样的递归操作。
平均时间复杂度为O(nlogn)。
c++代码:
void QuickSort(int iArr[], int iLeft, int iRight) { int i = iLeft; int j = iRight; int iKey = iArr[i];//将当前区间的第一个元素作为关键数据 if (iLeft >= iRight) return ;//不能再划分,直接返回 while(i < j) { //将比iKey小的元素往前放 while(i < j && iArr[j] >= iKey) { j--; } iArr[i] = iArr[j]; //将比iKey大的元素往后放 while(i < j && iArr[i] <= iKey) { i++; } iArr[j] = iArr[i]; } iArr[i] = iKey;//将iKey放中间 QuickSort(iArr, iLeft, i - 1);//继续递归操作 QuickSort(iArr, i + 1, iRight); }希尔排序:
希尔排序是插入排序的一种。它是把元素按照下标的一定增量分组,再对每组使用直接插入排序。随着增量逐渐减少,每组包含的元素越来越多。当增量减少到1时,所有的元素正好分成1组。
平均时间复杂度为O(n^1.25。
c++代码:
void ShellSort(int iArr[], int iNum) { int i, j, iGap, k; for (iGap = iNum / 2; iGap > 0; iGap /= 2)//增量 { for (i = 0; i < iGap; i++)//遍历每个分组 { for (j = i + iGap; j < iNum; j += iGap)//遍历每个分组中的元素 { //对分组进行直接插入排序 int iTemp = iArr[j]; for (k = j - iGap; k >= 0 && iArr[k] > iTemp; k -= iGap) { iArr[k + iGap] = iArr[k]; } iArr[k + iGap] = iTemp; } } } }堆排序:
堆排序是利用了完全二叉树,它将元素列表组织成一个完全二叉树。第一轮操作过后,最大的元素将位于根节点,然后将根节点元素和最后一个节点元素对换。第二轮操作过后,第二大的元素将位于根节点(剩下N-1个元素中最大的元素),然后将根节点元素和倒数第二个节点元素对换。继续进行下去,直到整个二叉树是从小到大排列的。
平均时间复杂度为O(nlogn)。
c++代码:
void HeapAdjust(int iArr[], int i, int iNum) { //i是要调整的节点,执行该函数后以i为根节点的子树中, //i节点的值最大 int iLchild = 2 * i + 1; int iRchild = 2 * i + 2; int iMax = i; if (i <= iNum / 2 - 1) { if (iLchild < iNum && iArr[iLchild] > iArr[iMax]) { iMax = iLchild; } if (iRchild < iNum && iArr[iRchild] > iArr[iMax]) { iMax = iRchild; } if (i != iMax) { int iTemp = iArr[i]; iArr[i] = iArr[iMax]; iArr[iMax] = iTemp; HeapAdjust(iArr, iMax, iNum); } } } //将数组组织成完全二叉树 void BuildHeap(int iArr[], int iNum) { for (int i = iNum / 2 - 1; i >= 0; i--) { HeapAdjust(iArr, i, iNum); } } void HeapSort(int iArr[], int iNum) { BuildHeap(iArr, iNum); for (int i = iNum - 1; i > 0; i--) { //将当前最大值与当前最后的节点对换 int iTemp = iArr[0]; iArr[0] = iArr[i]; iArr[i] = iTemp; //对换后,重新调整 HeapAdjust(iArr, 0, i); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/emsoften/article/details/47663195