排序算法分为内部排序和外部排序,我们一般探讨的是内部排序。
内部排序分为以下几类:
1.插入排序
·直接插入排序
·希尔排序
2.交换排序
·冒泡排序
·快速排序·
3.选择排序
·简单选择排序
·堆排序
4.归并排序和基数排序·
面试中常考查的是冒泡排序、快速排序和堆排序
快速排序:
//快速排序
public static void fastSort(int[] nums, int low, int high) {
if (low < high) {
//递归调用
int pivotpos = Partition(nums, low, high);
fastSort(nums, low, pivotpos - 1);
fastSort(nums, pivotpos + 1, high);
}
}
public static int Partition(int[] nums, int low, int high) {
//一趟划分,将当前表中第一个元素设为枢轴,对表进行划分
int pivot = nums[low];
while (low < high) { //循环跳出条件
while (low < high && nums[high] >= pivot) --high;
nums[low] = nums[high];
while (low < high && nums[low] <= pivot) low++;
nums[high] = nums[low];
}
nums[low] = pivot;
return low;
}
算法性能分析:
快排的运行时间与划分是否对称有关,快排的最坏情况发生在两个区域分别包含n-1个元素和0个元素时,这种最大限度的不对称性若发生在每层递归上,即对应于初始排序表基本有序或基本逆序时,就得到最坏情况下的时间复杂度为O();在最理想的情况下,划分的两个子问题大小都不可能大于n/2,在这种情况下,快排的速度大大提升,此时时间复杂度为O()。快排是所有内部排序算法中平均性能最优的算法
堆排序:
public class heapSort {
public static void heapSort(int[] nums, int len) {
//初始建堆
buildMaxHeap(nums, len);
//n-1趟的交换和建堆过程
for (int i = len; i > 1; i--) {
int tmp = nums[i];
nums[i] = nums[1];
nums[1] = tmp;
headAdjust(nums, 1, i - 1);
}
}
public static void buildMaxHeap(int[] nums, int len) {
//反复调整堆
for (int i = len / 2; i > 0; i--)
headAdjust(nums, i, len);
}
public static void headAdjust(int[] nums, int k, int len) {
//将元素k为根的子树进行调整
nums[0] = nums[k]; //nums[0]暂存子树的根节点
for (int i = 2 * k; i <= len; i *= 2) {//沿key较大的子节点向下筛选
if (i < len && nums[i] < nums[i + 1])
i++;//取key较大的子节点的下标
if (nums[0] >= nums[i]) break;//筛选结束
else {
nums[k] = nums[i];//将nums[i]调整到双亲结点上
k = i;//修改k值以便继续向下筛选
}
}
nums[k] = nums[0]; //被筛选节点的值放入最终位置
}
public static void main(String[] args) {
//需要多出一位用作哨兵
int[] nums = {0, 53, 17, 78, 9, 45, 65, 87, 32};
heapSort(nums, nums.length - 1);
for (int i = 1; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
}
}
算法性能分析:
堆空间仅使用了常数个辅助单元,所以空间复杂度为O(1),最好最坏和平均的时间复杂度均为O(),且堆排序也是一种不稳定的排序。
冒泡排序:
public class bubbleSort {
public void BubbleSort(int[] nums, int n) {
for (int i = 0; i < n - 1; i++) {
boolean flag = false;//标识本趟冒泡是否发生交换
for (int j = n - 1; j > i; j--)
if (nums[j - 1] > nums[j]) {
//交换
//一趟下来最小的就在最左边了
int tmp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = tmp;
//修改标志位
flag = true;
}
//本趟遍历后没有发生交换,说明表已经有序
if (flag == false) return;
}
}
}
算法性能分析:
空间复杂度为O(1),最好情况下走一趟比较次数为n-1,移动次数为0,故最好情况下的时间复杂度为O(n),最坏和平均的时间复杂度为O(),但冒泡排序算法确是一个稳定的算法。