赞
踩
冒泡排序的基本思想是比较相邻两个元素的大小,如果顺序不对则交换它们的位置,一直重复这个过程直到整个序列有序。它的时间复杂度为O(n^2),因此对于较大的数据集不太适用,但对于小型数据集和教学目的来说是一种不错的选择。
(1)设数组为长度为n。
(2)从第一个元素开始,比较数组相邻的元素。如果前一个元素比后一个元素大,则交换他们的位置。经过一轮循环后,最后一个元素一定是本轮中最大的元素,因此下一轮循环时只需要比较前n-1个元素即可。
(3)不计最后一个元素,在剩下的n-1个元素中,重复步骤2,直到第一个元素(即在n-1个元素数中,继续比较相邻的元素)。
(4)重复步骤3,直到第一个元素结束,此时数组升序。
- def bubble_sort(arr):
- n = len(arr)
- for i in range(n):
- # 经过i轮冒泡后,后i个元素已经有序,不需要再比较
- for j in range(n - i - 1):
- if arr[j] > arr[j + 1]:
- # 如果前一个元素比后一个元素大,则交换它们的位置
- arr[j], arr[j + 1] = arr[j + 1], arr[j]
- return arr
- // 冒泡排序
- vector<int> BubbleSort(vector<int>& arr){
- //for循环用来控制相邻元素比较的元素
- //(即经过i轮冒泡后,后i个元素已经有序,不需要再比较)
- for(int i = arr.size() - 1; i > 0; i--){
- //比较数组相邻元素
- for(int j = 0; j < i; j++){
- if(arr[j + 1] < arr[j]){
- swap(arr[j + 1], arr[j]);
- }
- }
- }
- return arr;
- }
选择排序的基本思路是每次从未排序的数列中选择最小(或最大)的元素(最小即升序,最大即降序),将其放到已排序数列的末尾。重复这个过程,直到所有元素都被排序为止。选择排序是一种简单但效率较低的排序算法,其时间复杂度为O(n^2),不适用于大规模数据的排序。
(1)设数组长度为n。
(2)从数组中找到最小的元素,并记录其下标。
(3)将最小元素与第1个元素交换位置。
(4)在剩下的n-1个元素中,找到最小的元素,记录其下标。
(5)将最小元素与第2个元素交换位置。
(6)重复步骤4-5,直到排序完成。
- def selection_sort(arr):
- n = len(arr)
- for i in range(n):
- # 找到未排序部分的最小值
- min_index = i
- for j in range(i+1, n):
- if arr[j] < arr[min_index]:
- min_index = j
- # 将最小值与当前位置交换
- arr[i], arr[min_index] = arr[min_index], arr[i]
- return arr
- // 选择排序
- vector<int> SelectSort(vector<int>& arr){
- for(int i = 0; i < arr.size(); i++){
- // 记录最小值以及最小值对应的索引
- int min = arr[i];
- int min_index = i;
- // 找到未排序数列中的最小值
- for(int j = i; j < arr.size(); j++){
- if(arr[j + 1] < min){
- min = arr[j + 1];
- min_index = j + 1;
- }
- }
- // 将最小值放到已排序数列的末尾(即将最小值放在数组第一位,依次类推)
- swap(arr[min_index], arr[i]);
- }
- return arr;
- }

在这个实现中,我们使用了两个循环。外循环从0到n-1遍历数组,表示已排序部分的范围;内循环从i+1到n遍历数组,用于查找未排序部分的最小值。当找到最小值时,我们将其与当前位置进行交换,这样就将最小值放到了已排序部分的末尾。
最后,我们返回排好序的数组。这个实现的时间复杂度为O(n^2),空间复杂度为O(1)。
插入排序(Insertion Sort)的基本思路是将一个未排序的数列,逐个插入到已排序的数列中,使得插入后的数列仍然有序。插入排序的优点是实现简单,适用于小规模的数据排序,时间复杂度为O(n^2),空间复杂度为O(1)。但是,对于大规模数据的排序,插入排序的效率较低。
(1)设数组长度为n。
(2)将第1个元素看成已排序部分,第2个元素到第n个元素看成未排序部分。
(3)从未排序部分取出第1个元素,将其插入已排序部分的合适位置。此时已排序部分的长度为1。
(4)从未排序部分取出第2个元素将其插入已排序部分的合适位置。此时已排序部分的长度为2。
(5)重复步骤4,直到所有元素都被插入到已排序部分。
- def insertion_sort(arr):
- n = len(arr)
- for i in range(1, n):
- # 获取当前位置的值
- key = arr[i]
- # 将当前位置的值插入已排序部分的合适位置
- j = i - 1
- while j >= 0 and arr[j] > key:
- arr[j+1] = arr[j]
- j -= 1
- arr[j+1] = key
- return arr
- // 插入排序
- vector<int> InsertOrder(vector<int>& arr){
- //外层循环获取未排序部分的元素
- for(int i = 1; i < arr.size(); i++){
- int key = arr[i];
- int j = i-1;
- // 将未排序部分的元素插入到已排序部分的合适位置
- while(j >= 0 && key < arr[j]){
- arr[j + 1] = arr[j];
- j = j - 1;
- }
- arr[j + 1] = key;
- }
- return arr;
- }
快速排序的基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据小,然后再按此方法对这两部分数据分别进行快速排序,以达到整个序列有序的目的。快速排序的时间复杂度为 O(nlogn),空间复杂度为 O(logn)。在实际应用中,快速排序是一种常用的排序算法,可以用于处理各种规模的数据。
(1)选取一个基准元素(pivot),通常选择第一个或最后一个元素。
(2)将序列中所有元素按照基准元素分成两部分,小于基准元素的放在左边,大于基准元素的放在右边,相等的可以放在任意一边。
(3)对左右两部分递归进行快速排序,直到所有元素有序。
- def quick_sort(arr):
- if len(arr) <= 1:
- return arr
- else:
- pivot = arr[0]
- left = [x for x in arr[1:] if x < pivot]
- right = [x for x in arr[1:] if x >= pivot]
- return quick_sort(left) + [pivot] + quick_sort(right)
- // 快速排序
- void QuickSort(vector<int>& arr, int i, int j) { // arr为待排序数组,i和j分别为左边界和右边界
- if(i >= j) return; //递归结束条件
- int low = i, high = j, key = arr[low]; //low和high为左右指针,key为基准,现在可以看做low的位置是空的
- while(low < high){
- while(low < high && arr[high] > key){ //从右到左,寻找比基准小的数
- high--;
- }
- if(low < high){
- arr[low] = arr[high];
- }
- while(low < high && arr[low] < key){ //从左到右,寻找比基准大的数
- low++;
- }
- if(low < high){
- arr[high] = arr[low];
- }
- }
-
- arr[low] = key; //当前low=high,左边全部小于基准,右边全部大于基准,因此在该位置插入基准值
- QuickSort(arr, i, low - 1);
- QuickSort(arr, low + 1, j);
- }

堆排序(Heap Sort)是一种基于完全二叉树的排序算法,它的基本思想是将待排序的序列看成一棵完全二叉树,并将其构建成一个大根堆(或小根堆),然后将堆顶元素与堆底元素交换(因为堆顶元素最大),并重新调整堆,使得剩余元素仍满足堆的性质,重复以上操作,直到所有元素有序为止。堆排序的时间复杂度为 O(nlogn),空间复杂度为 O(1)。在实际应用中,堆排序是一种常用的排序算法,可以用于处理各种规模的数据。
(1)将待排序的序列构建成一个大根堆(或小根堆),这一步可以使用 Heapify 操作实现,即从最后一个非叶子节点开始,依次向下调整每个子树,使其满足堆的性质。
(2)将堆顶元素与堆底元素交换,并将堆的大小减一,(即将最大的元素放到最后)。
(3)对堆顶元素进行下沉操作,使其重新满足堆的性质(即在剩余的数中找最大的元素)。
(4)重复步骤 2 和 3,直到堆的大小为 1,此时整个序列有序。
- # 最大堆调整
- # 大根堆:每个节点的值大于或等于它的左右孩子节点的值,升序:大根堆,降序:小根堆
- def heapify(arr, parent, size):
- child = 2 * parent + 1
- # 如果当前父节点存在右孩子,且右孩子值大于左孩子值,使当前孩子节点指向右孩子
- while child < size:
- if child + 1 < size and arr[child] < arr[child + 1]:
- child += 1
- # 如果当前孩子节点的值大于父节点值,交换它们
- if arr[child] > arr[parent]:
- arr[child], arr[parent] = arr[parent], arr[child]
- # 调整后,该节点之后的所有父节点也需要调整
- parent, child = child, 2 * child + 1
- else:
- break
-
- def heap_sort(arr):
- size = len(arr)
- # 构造大根堆
- for i in range(size // 2 - 1, -1, -1):
- heapify(arr, i, size)
- # 堆排,将大根堆转成有序数组
- for i in range(size - 1, 0, -1):
- arr[0], arr[i] = arr[i], arr[0]
- size -= 1
- heapify(arr, 0, size)
- return arr
-
- list1 = [8, 3, 1, 2, 6, 4, 7, 5]
- res5 = heap_sort(list1)
- print(res5)

- // 堆排序
- // 构建大根堆
- void Heapify(vector<int>& arr, int parent, int size){
- int child = 2 * parent + 1;
- while(child < size){
- // 如果当前父节点存在右孩子,且右孩子值大于左孩子值,使当前孩子节点指向右孩子
- if(child + 1 < size && arr[child] < arr[child + 1]){
- child += 1;
- }
- // 如果当前孩子节点的值大于父节点值,交换它们
- if(arr[child] > arr[parent]){
- swap(arr[child], arr[parent]);
- // 调整后,该节点之后的所有父节点也需要调整
- parent = child;
- child = 2 * child + 1;
- }
- else
- break;
- }
- }
-
- // 堆排主函数
- void HeapSort(vector<int>& arr){
- int size = arr.size();
- // 构造大根堆
- for(int i = size / 2 - 1; i > -1; i--){
- Heapify(arr, i, size);
- }
- // 将大根堆转成有序数组(每一次调整后,将堆顶元素下沉)
- for(int i = size - 1; i > 0; i--){
- swap(arr[0], arr[i]);
- size -= 1;
- Heapify(arr, 0, size);
- }
- }

归并排序是一种基于分治策略的排序算法。它的基本思想是将待排序的序列不断地分成两个子序列,直到每个子序列只有一个元素,然后将这些子序列进行合并,直到最终得到一个有序序列。归并排序的时间复杂度为O(nlogn),其中n为待排序序列的长度。归并排序是稳定的排序算法,即相等元素的相对位置不会改变。
(1)将序列中待排序数字分为若干组,每个数字分为一组。
(2)将若干组两两合并,保证合并的组都是有序的。
(3)重复第二步的操作,直到剩下最后一组即为有序数列。
- def merge_sort(arr):
- if len(arr) <= 1:
- return arr
-
- mid = len(arr) // 2
- left_arr = arr[:mid]
- right_arr = arr[mid:]
-
- left_arr = merge_sort(left_arr)
- right_arr = merge_sort(right_arr)
-
- return merge(left_arr, right_arr)
-
- def merge(left_arr, right_arr):
- i, j = 0, 0
- result = []
-
- while i < len(left_arr) and j < len(right_arr):
- if left_arr[i] <= right_arr[j]:
- result.append(left_arr[i])
- i += 1
- else:
- result.append(right_arr[j])
- j += 1
-
- result += left_arr[i:]
- result += right_arr[j:]
-
- return result

- // 归并排序
- // 合并函数, 两两合并,两组元素谁小谁放入结果序列中,保证合并的组都是有序的
- vector<int> merge(vector<int> left_arr, vector<int> right_arr){
- int i = 0, j = 0; // i指向组1的第一个元素,j指向组2的第一个元素
- vector<int> result;
- while(i < left_arr.size() && j < right_arr.size()){
- if(left_arr[i] <= right_arr[j]){
- result.push_back(left_arr[i]);
- i += 1;
- }
- else{
- result.push_back(right_arr[j]);
- j += 1;
- }
- }
- // 直到其中一个子序列为空,然后将另一个子序列中剩余的元素依次放入结果序列中
- result.insert(result.end(),left_arr.begin() + i,left_arr.end());
- result.insert(result.end(),right_arr.begin() + j,right_arr.end());
- cout<<"(";
- for(auto c: result){
- cout<<c;
- }
- cout<<")";
- return result;
- }
-
- // 归并排序主函数
- vector<int> MergeSort(vector<int> arr){
- if(arr.size() <= 1)
- return arr;
- int mid = arr.size() / 2;
- // vector的切片
- vector<int> left_arr(arr.begin(), arr.begin() + mid);
- vector<int> right_arr(arr.begin() + mid, arr.end());
- // 将序列中待排序数字分为若干组,每个数字分为一组
- left_arr = MergeSort(left_arr);
- right_arr = MergeSort(right_arr);
-
- return merge(left_arr, right_arr);
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。