手撕排序算法:快速排序


快速排序(Quick Sort)是一种分而治之的排序算法。它通过选择一个基准元素,将数组分为两部分,一部分的元素都比基准小,另一部分的元素都比基准大,然后对这两部分再进行快速排序,最终得到有序的数组。

1.算法思想

第一步、选择基准元素:从数组中选择一个元素作为基准。
第二步、分割数组:将比基准小的元素放在基准的左边,比基准大的元素放在基准的右边。
第三步、递归排序:对基准左边和右边的子数组分别进行快速排序。
重复步骤一至三,直到子数组的长度为1或0。

2.算法分析

2.1时间复杂度

最优情况:当每次选择的基准元素正好将数组分成两等分时,快速排序的时间复杂度是
o(nlogn)。
-最坏情况:当每次选择的基准元素是最大或最小元素时,快速排序的时间复杂度是O(n^ 2)
平均情况:在平均情况下,快速排序的时间复杂度也是O(nlogn)。

2.2空间复杂度

快速排序的空间复杂度是O(log),因为在递归调用中需要使用栈来存储中间结果。这意味着
在排序过程中,最多需要O(log)的额外空间来保存递归调用的栈帧。

3.算法优缺点

3.1算法的优点

1.高效性:快速排序在大多数情况下具有较高的排序效率。
2.适应性:适用于各种数据类型的排序。
3.原地排序:不需要额外的存储空间。

3.2算法的缺点

1.最坏情况性能:在最坏情况下,快速排序的时间复杂度可能退化为O(2)。
2.不稳定性:快速排序可能会破坏排序的稳定性,即相同元素的相对顺序可能会改变。

4.优化方案

1.选择合适的基准:选择合适的基准元素可以提高算法的性能。
2.三数取中:通过选择中间元素作为基准,可以避免最坏情况的出现。
3.分区的改进:可以使用双指针或其他方法来改进分区的过程,提高算法的效率。
4.小数组使用插入排序:对于小数组,可以直接使用插入排序,避免不必要的递归。

5.代码描述(C语言)

void Swap(int* a,int* b) {  
    int temp = *a;  
    *a = *b;  
    *b = temp;  
}  
// 1 ,3 ,4 ,2 ,6 ,5 ,9 ,7 ,8  
//         indx  
// 2 .3 .4 .1 .6 .5 .9 .7 .8  
// i                       j  
int Partition(int* num,int low,int high) {  
    int indx = low + rand()%(high - low + 1);  
    Swap(&num[indx],&num[0]);  
    int i = low;  
    int j = high;  
    int x = num[i];  
    while (i < j) {  
        while (i < j && num[j] > x) {  
            j--;  
        }  
        if(i < j) {  
            Swap(&num[i],&num[j]);  
            i++;  
        }  
        while (i < j && num[j] < x) {  
            i++;  
        }  
        if (i < j) {  
            Swap(&num[i].&num[j]) {  
                j--;  
            }  
        }  
    }  
    num[i] = x;  
    return i;  
}  
//num[low:high]  
void QuickSort(int num[],int low,int high) {  
    if(high >= low) {  
        return;  
    }  
    int pi = Partition(num,low,high);  
    QuickSort(num,low,pi - 1);  
    QuickSort(num,pi + 1, high);  
}

6.实战

6.1力扣217 存在重复元素

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false

void Swap(int* a, int* b) {  
  
        int temp = *a;  
  
        *a = *b;  
  
        *b = temp;  
  
}  
  
    
int Partition(int* num, int low, int high) {  
  
  
        int indx = low + rand() % (high - low + 1);  
  
        Swap(&num[indx], &num[low]);  
  
        int i = low;  
  
        int j = high;  
  
        int x = num[low]; // 随机选择的基准元素  
  
        while (i < j) {  
  
                while (i < j && num[j] >= x) {  
  
                        j--;  
  
                }  
  
                if (i < j) {  
  
                        Swap(&num[i], &num[j]);  
  
                        i++;  
  
                }  
  
                while (i < j && num[i] <= x) {  
  
                        i++;  
  
                }  
  
                if (i < j) {  
  
                        Swap(&num[i], &num[j]);  
  
                        j--;  
  
                }  
  
        }  
  
        Swap(&num[low], &num[i]); // 将基准元素放到正确的位置  
  
        return i;  
  
}  
  
    
void QuickSort(int num[], int low, int high) {  
  
        if (high <= low) {  
  
                return;  
  
        }  
  
        int pi = Partition(num, low, high);  
  
        QuickSort(num, low, pi - 1);  
  
        QuickSort(num, pi + 1, high);  
  
}

  

bool containsDuplicate(int* num, int numsSize) {

    QuickSort(num, 0, numsSize - 1);

    for (int i = 1; i < numsSize; i++) {

        if (num[i] == num[i - 1]) {

            return true;

        }

    }

    return false;

}

6.2 力扣169多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

void Swap(int* a,int* b) {    
int temp = *a;    
    *a = *b;    
    *b = temp;    
}  // 1 ,3 ,4 ,2 ,6 ,5 ,9 ,7 ,8  //         indx  // 2 .3 .4 .1 .6 .5 .9 .7 .8  // i                       j  int Partition(int* num,int low,int high) {    
int indx = low + rand()%(high - low + 1);    
    Swap(&num[indx],&num[0]);    
    int i = low;    
    int j = high;    
    int x = num[i];    
    while (i < j) {    
while (i < j && num[j] > x) {    
j--;    
        }    
if(i < j) {    
Swap(&num[i],&num[j]);    
            i++;    
        }    
while (i < j && num[j] < x) {    
i++;    
        }    
if (i < j) {    
Swap(&num[i],&num[j]);    
            j--;     
        }    
}    
num[i] = x;    
    return i;    
}  //num[low:high]  void QuickSort(int num[],int low,int high) {    
if(high >= low) {    
return;    
    }    
int pi = Partition(num,low,high);    
    QuickSort(num,low,pi - 1);    
    QuickSort(num,pi + 1, high);    
}  
int majorityElement(int* nums, int numsSize) {  
    QuickSort(nums,0,numsSize - 1);  
    return nums[numsSize / 2];  
}
  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写代码的大学生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值