C#两路list数组归并去重

两个相同类型已排序数据进行合并,虽然list数组中有AddRange方法,但它只是把第二个数组从第一个数组末尾插入,假如两个数组有重复数据,保存进去。
还有Union方法合并去重,首先会从第一个数组进行检查然后再把第二个数组数据从第一个数组依次从末尾插入,但相对于自定义类型排序还是不能有效解决问题。

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

Examples

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4
 5 namespace Examples.Utils
 6 {
 7     public static class CollectionUtils
 8     {
 9         public static IList<T> MergeSortedLists<T>(Comparison<T> comparision, IList<T> list1, IList<T> list2)
10         {
11             var mergedList = new List<T>(list1.Count + list2.Count);
12             int i = 0, j = 0;
13             while (i < list1.Count && j < list2.Count)
14             {
15                 var result = comparision(list1[i], list2[j]);
16                 if (result <= 0)
17                 {
18                     if (result == 0)
19                     {
20                         j++;
21                     }
22                     mergedList.Add(list1[i++]);
23                 }
24                 else
25                 {
26                     mergedList.Add(list2[j++]);
27                 }
28             }
29             while (i < list1.Count)
30             {
31                 mergedList.Add(list1[i++]);
32             }
33             while (j < list2.Count)
34             {
35                 mergedList.Add(list2[j++]);
36             }
37             return mergedList;
38         }
39     }
40 }

TestExamples

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using NUnit.Framework;
 5
 6 namespace Examples.Utils.Tests
 7 {
 8     [TestFixture]
 9     public class CollectionUtilsTests
10     {
11         [Test]
12         public void Merge2TestNoDuplicate()
13         {
14             var list1 = new List<int> {100, 50, 20, 10, 1};
15             var list2 = new List<int> {500, 70, 30, 15, 5};
16             var mergedList = CollectionUtils.MergeSortedLists(IntegerComparision, list1, list2);
17             var expectedList = GetExpectedMergedList(IntegerComparision, list1, list2);
18             Assert.AreEqual(expectedList.Count, mergedList.Count);
19             CollectionAssert.AreEqual(expectedList, mergedList);
20         }
21
22         [Test]
23         public void Merge2TestWithDuplicates()
24         {
25             var list1 = new List<int> {100, 50, 20, 10, 1};
26             var list2 = new List<int> {500, 70, 50, 15, 1};
27             var mergedList = CollectionUtils.MergeSortedLists(IntegerComparision, list1, list2);
28             var expectedList = GetExpectedMergedList(IntegerComparision, list1, list2);
29             Assert.AreEqual(expectedList.Count, mergedList.Count);
30             CollectionAssert.AreEqual(expectedList, mergedList);
31         }
32
33         [Test]
34         public void Merge2TestNoOverlap1()
35         {
36             var list1 = new List<int> {500, 300, 250, 150, 120};
37             var list2 = new List<int> {100, 50, 20, 10, 1};
38             var mergedList = CollectionUtils.MergeSortedLists(IntegerComparision, list1, list2);
39             var expectedList = GetExpectedMergedList(IntegerComparision, list1, list2);
40             Assert.AreEqual(expectedList.Count, mergedList.Count);
41             CollectionAssert.AreEqual(expectedList, mergedList);
42         }
43
44         [Test]
45         public void Merge2TestNoOverlap2()
46         {
47             var list1 = new List<int> {100, 50, 20, 10, 1};
48             var list2 = new List<int> {500, 300, 250, 150, 120};
49             var mergedList = CollectionUtils.MergeSortedLists(IntegerComparision, list1, list2);
50             var expectedList = GetExpectedMergedList(IntegerComparision, list1, list2);
51             Assert.AreEqual(expectedList.Count, mergedList.Count);
52             CollectionAssert.AreEqual(expectedList, mergedList);
53         }
54
55         private static IList<T> GetExpectedMergedList<T>(Comparison<T> comparision, params IList<T>[] lists)
56         {
57             var set = new SortedSet<T>(new ComparisionComparer<T>(comparision));
58             foreach (var list in lists)
59             {
60                 foreach (var item in list)
61                 {
62                     if (!set.Contains(item))
63                     {
64                         set.Add(item);
65                     }
66                 }
67             }
68             return set.ToList();
69         }
70
71         private static int IntegerComparision(int x, int y)
72         {
73             return y - x;
74         }
75
76         private class ComparisionComparer<T> : IComparer<T>
77         {
78             private readonly Comparison<T> _comparision;
79
80             public ComparisionComparer(Comparison<T> comparision)
81             {
82                 _comparision = comparision;
83             }
84
85             public int Compare(T x, T y)
86             {
87                 return _comparision(x, y);
88             }
89         }
90     }
91 }
时间: 2024-10-13 02:50:19

C#两路list数组归并去重的相关文章

list数组归并去重

C#两路list数组归并去重 个相同类型已排序数据进行合并,虽然list数组中有AddRange方法,但它只是把第二个数组从第一个数组末尾插入,假如两个数组有重复数据,保存进去.还有Union方法合并去重,首先会从第一个数组进行检查然后再把第二个数组数据从第一个数组依次从末尾插入,但相对于自定义类型排序还是不能有效解决问题. 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即

leetcode 题解:Merge Sorted Array(两个已排序数组归并)

题目: Given two sorted integer arrays A and B, merge B into A as one sorted array. Note:You may assume that A has enough space (size that is greater or equal to m + n) to hold additional elements from B. The number of elements initialized in A and B ar

刷题之路第四题--取两个顺序数组的数值的中位数

Median of Two Sorted Arrays 简介:取两个顺序数组的数值的中位数 问题详解: 给定两个排序的数组nums1和nums2分别为m和n,我们需要的是两个数组中所组成一个数列的中位数. 注意: 1.需要判断数组NPE 2.结果不是int 举例 1: nums1 = [1, 3] nums2 = [2] 中位数是 2.0 2: nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3)/2 = 2.5 JAVA 实现方法一: 通过NPE判断后将两个数组

混合两个有序int数组到另一个有序数组并去重

题目:两个有序数组a和b,混合之,放在另一个数组c中,使得c也是有序数组(升序),去除重复的项. 虽然觉得不是很简便,但代码如下: int merge_array (int *a , int *b, int *c, int n1, int n2) { if (n1 < 0 || n2 < 0) { return -1; } int i = 0; int j = 0; int k = 0; int count = 0; while (i < n1 && j < n2)

两路归并排序

链表两路归并 #include<iostream> #include<assert.h> using namespace std; struct node { int val; node * next; node(int v) { val=v; next=NULL; } }; node * merge(node* list1 , node * list2) { assert(list1!=NULL&&list2!=NULL);//括号中是希望出现的正确的情况  no

求两个有序数组的中位数

这是我做的第二个leetcode题目,一开始以为和第一个一样很简单,但是做的过程中才发现这个题目非常难,给人一种“刚上战场就踩上地雷挂掉了”的感觉.后来搜了一下leetcode的难度分布表(leetcode难度及面试频率)才发现,该问题是难度为5的问题,真是小看了它!网上搜了很多答案,但是鲜见简明正确的解答,唯有一种寻找第k小值的方法非常好,在此整理一下. 首先对leetcode的编译运行吐槽一下:貌似没有超时判断,而且small和large的数据集相差很小.此题一开始我采用最笨的方法去实现,利

STM32F207 两路ADC连续转换及GPIO模拟I2C给Camera Sensor初始化参数

1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯片,是I2C是8位宽的,而镁光的地址是8位,而数据位是16个字节, 其实不管是8位还是16位,每次发送都是8个字节然后一个应答位,所以只要稍微改下代码即可. 3.实现两路ADC连续转换,两路ADC转换:一路是检测锂电池电压:一路是检测压力传感器,其实都是检测电压,当检测到压力为零,并累计多长时间后进

PHP数组合并+与array_merge的区别分析 &amp; 对多个数组合并去重技巧

PHP中两个数组合并可以使用+或者array_merge,但之间还是有区别的,而且这些区别如果了解不清楚项目中会要命的! 主要区别是两个或者多个数组中如果出现相同键名,键名分为字符串或者数字,需要注意 1)键名为数字时,array_merge()后面的值将不会覆盖原来的值,而是附加到后面,但+合并数组则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉(不是覆盖) 2)键名为字符串时,array_merge()此时会覆盖掉前面相同键名的值,但+仍然把最先出现的值作为最

[算法]对于已排好序的数组进行去重

最近项目中遇到一个场景,需要对排好序的数组进行去重(场景就是对同时获取两个频道的消息列表时做一个合并,而消息列表里的数据已经是排序好的), 经过思考后,尝试写了一个,感觉还算简洁,这里分享一下,如有有缘人可以参考,遇到问题还望指正,欢迎讨论:) 1 #include <iostream> 2 3 using namespace std; 4 5 #define NUM 7 6 7 int main(){ 8 9 int a[NUM] = {1, 1, 2, 2, 3, 5, 5}; 10 11