iOS算法(一)快速排序算法

快速排序是当遇到较大数据时,排序快,高效的方法(公司面试时,基本上会被问到...)

该方法的基本思想是:

1.先从数列中取出一个数作为基准数。

2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

3.再对左右区间重复第二步,直到各区间只有一个数。

简单地理解就是,找一个基准数(待排序的任意数,一般都是选定首元素),把比小于等于基准数的元素放到基准数的左边,把大于基准数的元素放在基准数的右边.排完之后,在把基准数的左边和右边各看成一个整体,  左边:继续选择基准数把小于等于基准数的元素放到基准数的左边,把大于基准数的元素放在基准数的右边,右边也是一样..直到各区间只有一个数位置.

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。

图片诠释上面的思想

技术分享

 

<书面语解释>

1、算法思想
     快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

1)分治法的基本思想
     分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

2)快速排序的基本思想
     设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解: 
     在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
  注意:
     划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
     R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
                  其中low≤pivotpos≤high。
②求解: 
     通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

③组合: 
     因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

代码实现:

 

#import <Foundation/Foundation.h>

#define COUNT 100      //定义数组元素的个数

int a[COUNT], n; //定义全局变量,这两个变量需要在子函数中使用

//给快速排序方法连个参数,开始位置(左),和结束位置(右)

void quicksort(int left, int right){

    int i, j, t, temp;

    if(left > right)  //开始位置坐标大于结束位置坐标时,直接return,结束下面的操作

        return;

    temp = a[left];  //temp中存的就是基准数(基准数是随机的,但一般都是第一个元素)

    i = left;

    j = right;

    while(i != j)

    {

        //顺序很重要,要先从右边开始找

        while(a[j] >= temp && i<j)

            j--;

        //再找左边的

        while(a[i] <= temp && i<j)

            i++;

        //交换两个数在数组中的位置

        if(i < j)

        {

            t = a[i];

            a[i] = a[j];

            a[j] = t;

        }

    }

    //此时i = j,最终将基准数归位

    a[left] = a[i];

    a[i] = temp;

    //递归调用

    quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程

    quicksort(i+1, right);//继续处理右边的 ,这里是一个递归的过程

}

 

int main(int argc, const char * argv[])

{

 

    int i;

    //读入数据

    scanf("%d", &n);

    for(i = 1; i <= n; i++){

        scanf("%d", &a[i]);

    }

    quicksort(1, n); //快速排序调用

    

    //输出排序后的结果

    for(i = 1;i <= n; i++){

        printf("%d ", a[i]);

    }

    return 0;

}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 C++ 实现的外部排序示例代码: ```cpp #include <fstream> #include <iostream> #include <algorithm> #include <queue> #include <string> #include <vector> using namespace std; // 定义每个初始归并段的大小 const int chunk_size = 10 * 1024 * 1024; // 10MB // 读取并分割原始数据文件 void split_file(const string& input_file) { ifstream in(input_file, ios::binary); int chunk_num = 0; while (true) { char* buffer = new char[chunk_size]; in.read(buffer, chunk_size); int len = in.gcount(); if (len == 0) { break; } chunk_num++; // 将每个初始归并段写入一个单独的文件 ofstream out("chunk_" + to_string(chunk_num), ios::binary); out.write(buffer, len); delete[] buffer; } in.close(); } // 对每个初始归并段进行排序 void sort_chunk(const string& chunk_file) { ifstream in(chunk_file, ios::binary); in.seekg(0, ios::end); int len = in.tellg(); in.seekg(0, ios::beg); char* buffer = new char[len]; in.read(buffer, len); // 使用快速排序(quick sort)对数据进行排序 sort(buffer, buffer + len); // 将排序结果写入新的归并段文件 ofstream out("sorted_" + chunk_file, ios::binary); out.write(buffer, len); delete[] buffer; in.close(); out.close(); } // 多路归并 void merge_files(const string& output_file, const vector<string>& input_files) { // 将所有归并段文件打开并读取第一个元素 ofstream out(output_file, ios::binary); vector<ifstream> ins; vector<char> values; for (const string& input_file : input_files) { ins.emplace_back(input_file, ios::binary); char value; ins.back().read(&value, 1); values.push_back(value); } // 从堆中取出最小元素并写入输出文件,然后读取下一个元素并重新放入堆中 while (!values.empty()) { auto it = min_element(values.begin(), values.end()); char value = *it; int index = it - values.begin(); out.write(&value, 1); ins[index].read(&value, 1); if (ins[index].good()) { values[index] = value; } else { values.erase(it); ins[index].close(); } } out.close(); } // 外部排序 void external_sort(const string& input_file, const string& output_file) { split_file(input_file); // 对每个初始归并段进行排序 for (const auto& chunk_file : directory_iterator(".")) { if (chunk_file.is_regular_file() && chunk_file.path().string().find("chunk_") == 0) { sort_chunk(chunk_file.path().string()); } } // 递归地进行多路归并 vector<string> sorted_files; for (const auto& sorted_file : directory_iterator(".")) { if (sorted_file.is_regular_file() && sorted_file.path().string().find("sorted_") == 0) { sorted_files.push_back(sorted_file.path().string()); } } while (sorted_files.size() > 1) { vector<string> merged_files; for (int i = 0; i < sorted_files.size(); i += 2) { if (i + 1 < sorted_files.size()) { merge_files("merged_" + to_string(i / 2), {sorted_files[i], sorted_files[i+1]}); merged_files.push_back("merged_" + to_string(i / 2)); } else { merged_files.push_back(sorted_files[i]); } } sorted_files = merged_files; } // 将最终的归并段文件重命名为输出文件 rename(sorted_files[0].c_str(), output_file.c_str()); // 删除中间文件 for (const auto& file : directory_iterator(".")) { if (file.is_regular_file() && (file.path().string().find("chunk_") == 0 || file.path().string().find("sorted_") == 0 || file.path().string().find("merged_") == 0)) { remove(file.path().string().c_str()); } } } int main() { string input_file = "input.dat"; string output_file = "output.dat"; external_sort(input_file, output_file); return 0; } ``` 注意,在实际应用中,需要根据数据规模和内存大小等因素来调整初始归并段的大小和归并路数。此外,还需要考虑数据的类型和大小对排序和归并算法的影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值