归并排序

经典排序--归并排序

十年热恋 提交于 2019-12-03 10:10:37
归并排序的原理   归并排序是利用归并的思想实现的排序方法,该方法采用经典的分治策略(分治法将问题分成一些小的问题然后递归求解,而治的阶段则是将分的阶段得到的答案修补在一起,即分而治之)。 图解归并排序    下面我们以待排序数组 8,4,5,7,1,3,6,2,9,10为例,以图解的方式讲解归并排序的原理。   (1)分治原理图(由于图片太大,没法截全,我进行了一定压缩,所以看起来有点奇怪...)   从图中可以看出,归并排序是先将数组进行拆分,拆分到剩余一个关键字,这是一个从大到小的过程。然后再进行治理,治理的过程也就是进行合并的过程,合并时会保证左右两边的数组内部各自有序。然后将两个有序的数组合并到一个数组中,且合并后的数组有序。总结就是:递归拆分,回溯合并,合并时左右两个数组内部有序。   (2)递归原理图   在看递归原理图前,我们先看下归并排序的代码,如下所示 1 public class MergeSort { 2 private static int count = 1; 3 public static void main(String[] args) { 4 int[] arr = {8, 4, 5, 7, 1, 3, 6, 2, 9, 10}; 5 int[] temp = new int[arr.length]; 6 split(arr, 0, arr

归并排序 - 递归非递归实现java

瘦欲@ 提交于 2019-12-03 09:33:21
1.归并排序思想: 以2路归并为例,一个有n个记录的序列可以看作n个长度为1的有序子序列,将其两两合并成n/2(向上取整)个长度为2或1的有序序列,当有奇数个记录时为1,重复归并,直到得到一个长度为n的有序序列。 2.归并排序的复杂度: 递归:时间复杂度O( nlongn ),空间复杂度O( n+longn ) 非递归:时间复杂度O( nlongn ),空间复杂度O( n ) 所以用到归并排序,还是优先考虑非递归吧。 3.递归实现 1 public void mergeSort1(int[] data){ 2 msort(data,0,data.length-1); 3 } 4 5 public void msort(int[] data, int start, int end){ 6 if(start < end){ 7 int mid = (start + end) >>> 1; 8 msort(data,start,mid); 9 msort(data,mid+1,end); //当mid+1 == end时,子序列长度为1,退出msort,进入merge()排序 10 merge(data,start,mid,end); 11 } 12 } 13 14 public void merge(int[] data, int start, int mid, int end){

快速排序,归并排序,堆排序的数组和单链表实现

和自甴很熟 提交于 2019-12-03 07:11:42
原文链接: https://www.cnblogs.com/DarrenChan/p/8807112.html 这三个排序的时间复杂度都是O(nlogn),所以这里放到一起说。 回到顶部 1. 快速排序 # 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 步骤为: 从数列中挑出一个元素,称为"基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 最优时间复杂度:O(nlogn) 最坏时间复杂度:O(n2) 稳定性:不稳定 从一开始快速排序平均需要花费O(n log n)时间的描述并不明显

归并排序(逆序对数)

匿名 (未验证) 提交于 2019-12-03 00:43:02
ll qans; // 记录答案 int date[maxn]; // 数据数组 int tarray[maxn]; // 归并排序的中间数组 // POJ - 2299 SGU - 180 void merge( int arr[], int left, int right, int tarr[]) { if (left>=right) return ; int m = (left+right) >> 1 ; merge(arr, left, m, tarr); merge(arr, m + 1 , right, tarr); int i,j, cnt; i = left; j = m+ 1 ; cnt = 0 ; while (i<=m && j<= right) { if (arr[i] <= arr[j]) tarr[cnt ++] = arr[i++ ]; else { qans += (ll)m - i + 1 ; // 求逆序对. tarr[cnt++] = arr[j++ ]; } } while (i<=m) tarr[cnt++] = arr[i++ ]; while (j<=right) tarr[cnt++] = arr[j++ ]; for (i= 0 ; i<cnt; ++i) arr[left++] = tarr[i]; } View Code 原文

LeetCode 148. 排序链表

匿名 (未验证) 提交于 2019-12-03 00:39:02
使用归并排序的思想 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: //使用归并排序 void merge(ListNode* &head, ListNode* &mid, ListNode* &end){ if(head==mid && mid==end) return; ListNode* p=head, *p1=mid->next; vector<int> valList; int K=0; while(p!=mid->next && p1!=end->next){ if(p->val<=p1->val){ valList.push_back(p->val); K++; p=p->next; } else{ valList.push_back(p1->val); K++; p1=p1->next; } } while(p!=mid->next){ valList.push_back(p->val); K++; p=p->next; } while(p1!=end->next){ valList

leetcode+多路归并排序

匿名 (未验证) 提交于 2019-12-03 00:32:02
点击打开链接 //多路归并 struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* head = new ListNode(0); ListNode* temp = head; while(l1 && l2){ if(l1->val < l2->val){ head->next = l1; head = head->next; l1 = l1->next; } else{ head->next = l2; head = head->next; l2 = l2->next; } } if(l1){ head-> next =l1; } else{ head->next = l2; } return temp->next; } ListNode* mergeKLists(vector<ListNode*>& lists) { int n = lists.size(); if(n==0) return NULL; while (n>1) { int k = (n+1) / 2; for(int i

排序-----归并排序

匿名 (未验证) 提交于 2019-12-03 00:30:01
归并排序(MergeSort) 定义: 具体: 1.将一个乱序的数组按mid值分为两个数组(新建一个数组用于存储顺序元素)。 2.将一个数组中的项与另一个数组中的项进行比较,将较小的项复制到新的第三个数组中。 3.当到达一个数组的末尾后,将另一个数组的剩余元素复制到新的第三个数组中。 如图: import java.util.Arrays; public class MergeSort { public static <T extends Comparable<? super T>> void mergeSort(T[] a, int first, int last) { // 先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间 T[] tempArray = (T[]) new Comparable[a.length]; mergeSort(a, tempArray, first, last); } private static <T extends Comparable<? super T>> void mergeSort(T[] a, T[] tempArray, int first, int last) { if (first >= last) return; else { int mid = (first + last) / 2; //左边归并排序

归并排序

匿名 (未验证) 提交于 2019-12-03 00:27:02
《算法导论》第3版2.3.1分治法里提出了归并排序的算法 归并排序算法完全遵循分治模式 1)分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列 2)解决:使用归并排序递归地排序两个子序列 3)合并:合并两个已排序的子序列以产生已排序的答案 设置哨兵,它不可能为较小值 void mergeWithSentry ( int A [], int left , int mid , int right ) { int n1 = mid - left + 1 ; int n2 = right - mid ; int * L = new int [ n1 + 1 ]; int * R = new int [ n2 + 1 ]; for ( int i = 0 ; i < n1 ; ++ i ) L [ i ] = A [ left + i ]; for ( int j = 0 ; j < n2 ; ++ j ) R [ j ] = A [ mid + 1 + j ]; L [ n1 ] = INT_MAX ; R [ n2 ] = INT_MAX ; int i = 0 , j = 0 ; int k = left ; while ( k <= right ) { if ( L [ i ] <= R [ j ]) A [ k ++] = L [ i ++]; else A [ k +

归并排序-循环实现

匿名 (未验证) 提交于 2019-12-03 00:26:01
归并排序是建立在归并操作基础上的一种排序方法。归并操作,是指将两个已排序的子序列合并成一个有序序列的过程 归并操作的过程如下: 申请额外空间用于放置两个子序列归并后的结果 设置两个指针分别指向两个已排子序列的第一个位置 比较两个指针指向的元素,并将较小的那个放到1中申请的空间内,当前指针向后移动一格 重复3,直到某个子序列的指针指向该序列的结尾 将另一序列剩余元素全部放入到1中空间内,归并操作结束 /* 归并排序 - 循环实现 */ /* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置*/ void Merge ( ElementType A [], ElementType TmpA [], int L , int R , int RightEnd ) { /* 将有序的A[L]~A[R-1]和A[R]~A[RightEnd]归并成一个有序序列 */ int LeftEnd , NumElements , Tmp ; int i ; LeftEnd = R - 1 ; /* 左边终点位置 */ Tmp = L ; /* 有序序列的起始位置 */ NumElements = RightEnd - L + 1 ; while ( L <= LeftEnd && R <= RightEnd ) { if ( A [ L ] <= A [ R ] )

【书上讲解】归并排序的非递归写法

匿名 (未验证) 提交于 2019-12-03 00:13:02
描述 【题解】 让区间的长度L为1,2,4,...2^(n-1) 然后对每个位置i开始的长度为L的区间归并有序,用归并排序的方法就好,然后i跳转到i+L 复杂度仍然是log2(n)*n级别的,注意写的时候的一些细节。 比如一定要让最后L>=n的情况进行过一次,不然无法保证整个序列是有序的 【代码】 /* 归并排序非递归写法 */ #include <cstdio> const int N = 1e5 ; int a [ N + 10 ], b [ N + 10 ]; int n ; //把a这个数组在l1..r2这个区间分成两段[l1,r1]和[l2,r2];然后进行合并 void _Merge ( int a [], int b [], int l1 , int r1 , int l2 , int r2 ){ int i = l1 , j = l2 , k = l1 ; while ( i <= r1 && j <= r2 ){ if ( a [ i ]<= a [ j ]) b [ k ++]= a [ i ++]; else b [ k ++] = a [ j ++]; } while ( i <= r1 ) b [ k ++] = a [ i ++]; while ( j <= r2 ) b [ k ++] = a [ j ++]; } void _merge ( int