线性表的操作

1.Reverse

解法1 for循环

static void Reverse(SqList &a)
{
    //index++,last--
    for(int i=0,j=a.length-1;i<j;i++,j--)
    {
        //换位
        int obj2 = a.elem[i];
        a.elem[i]=a.elem[j];
        a.elem[j]=obj2;
    }
}

首位和末尾交换

解法2 while语句

static void Reverse(SqList &a)
{
    int index=0;
    int start = index;
    int end = (index + a.length) - 1;
    while (start < end)
        {
            int obj2 = a.elem[start];
            a.elem[start] = a.elem[end];
            a.elem[end] = obj2;
            start++;
            end--;
        }
     
}
两者效果相同

解法3

for(int i=0;i<a.length/2;i++)
{
    int obj2 = a.elem[i];
    a.elem[i]=a.elem[a.length-i-1];
    a.elem[a.length-i-1]=obj2;
}

直接将以a.length/2为基础,三种思想相同都是首末互换

2.删除指定重复元素的集合

即RemoveAll方法带有一个条件,即如下c#代码

public static void RemoveTest()
{
    List<int> list = new List<int>();
    list.Add(1);
    list.Add(1);
    list.Add(1);
    list.Add(2);
    list.RemoveAll(new Predicate<int>((int obj) => { return obj == 1; }));
}

方法1

static void RemoveAll(SqList &a,int number)
{
    int i=0;
    //find first element's index
    while(i<a.length && a.elem[i]!=number)
        i++;

    //move
    for(int j=i+1;j<a.length;j++)
    {
        if(a.elem[j]!=number)
        {
            a.elem[i]=a.elem[j];
            a.elem[j]=0;
            i++;
        }
        else
            a.elem[j]=0;
    }
    a.length=i;
}

方法2

这个算法关键在于记录删除元素的个数

static void RemoveAll2(SqList &a,int number)
{
    int i=0,k=0;
    
    while(i<a.length)
    {
        //record delete element count
        if(a.elem[i]==number)
        {
            k++;
            a.elem[i]=0;
        }
        else
        {
            //move
            a.elem[i-k]=a.elem[i];
            if(k>0)
            a.elem[i]=0;
        }
        i++;
    }

    a.length-=k;
}

两者也是等价的

其他删除条件的实现

根据你的需求改变上面划线部分的条件即可

其他的待更新

两个集合的合并(set 运算)

//取交集
public static void Intersect()
{
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
    int[] numbersB = { 1, 3, 5, 7, 8 };
    var list = new List<int>();
    for (int i = 0; i < numbersA.Length; i++)
    {
        for (int j = 0; j < numbersB.Length; j++)
        {
            if (numbersA[i].Equals(numbersB[j]))
            {
                list.Add(numbersA[i]);
            }
        }
    }
}
//差集
public static void Except()
{
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
    int[] numbersB = { 1, 3, 5, 7, 8,9 };
    var list = new List<int>();

    for (int i = 0; i < numbersA.Length; i++)
    {
        bool allow=true;
        for (int j = 0; j < numbersB.Length; j++)
        {
            if (numbersA[i].Equals(numbersB[j]))
            {
                allow=false;
            }
        }
        if (allow)
        {
            list.Add(numbersA[i]);
        }
    }
}

取并集是三个算法中最耗时间的,多了一次循环

//并集
public static void UnionTest()
{
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
    int[] numbersB = { 1, 3, 5, 7, 8 };

    List<int> list = new List<int>();
    //copy numbersA first
    foreach (var item in numbersA)
    {
        list.Add(item);
    }

    //compare two list
    for (int i = 0; i < numbersB.Length; i++)
    {
        int j = 0;
        while (j<numbersA.Length && numbersB[i]!=numbersA[j])
        {
            j++;
        }
        if(j==numbersA.Length)
            list.Add(numbersB[i]);
    }
    
}

Distinct操作

算法思想.如下
  1. 数组中只有2个元素比较后才知道是否重复,所以循环可以从索引值1开始
  2. 比较时将未重复的元素与当前元素重新比较
  3. 将比较的索引值与最大索引值比较

实际例子如下

  • 2,1,1,2
  • 2,1(k=1,j=1)
  • 2,1(k=1,j=1)
  • 2,1(k=0,j=1)
public static void DistinctTest()
{
    int[] numbers = { 2, 1, 2};
    List<int> list = new List<int>();
    int j = 0;
    for (int i = 1; i < numbers.Length; i++)
    {
        int k = 0;
        //compare distinct numbers with current number
        while (k <= j && numbers[k] != numbers[i])
            k++;

        //compare distinct number index with total count
        if (k > j)
        {
            j++;
            numbers[j] = numbers[i];
        }
    }

    int[] numbersB=new int[j+1];
    Array.Copy(numbers, numbersB, numbersB.Length);
}

两个有序数组合并成一个有序数组

1.合并成一个新数组

算法思想:

  1. 用一个循环先将A,B两个数组元素赋值到C中
  2. 其中毕竟有一个数组会先复制完成这取决于数组最后一个元素的大小,如果较大的大,则该数组等退出循环后再补上,即其中一组循环是不会进去的
public static void Merge1()
{
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
    int[] numbersB = { 1, 3, 7 };
    int i=0, j=0, k = 0;
    int[] numbersC = new int[numbersA.Length + numbersB.Length];
    while (i< numbersA.Length && j<numbersB.Length)
    {
        if (numbersA[i] < numbersB[j])
        {
            numbersC[k] = numbersA[i];
            i++;
        }
        else
        {
            numbersC[k] = numbersB[j];
            j++;
        }
        k++;
    }
    //only choice one
    while (i< numbersA.Length)
    {
        numbersC[k] = numbersA[i];
        i++;
        k++;
    }
    while (j < numbersB.Length)
    {
        numbersC[k] = numbersB[j];
        j++;
        k++;
    }
}

2.将数组A复制到B中,并保持有序(前提元素数量足够,不会溢出)

这个算法相当于是给数组B 新增A的元素,即在新增时候进行元素比较,若元素插入时在中间部分,则需要进行后移,对A数组的每个元素调用InsertOrder方法(循环)

    static int InsertOrder(SqList &a,int value)//删除线性表a中第i个元素起的k个元素    {
      int insertPosition=a.length-1;//10,20,30,40 add 25=>10,20,25,30,40
      int moveLength=a.length-1; //需要后移的数量 即i+1      
      while(insertPosition>=0 && a.elem[insertPosition]>value) insertPosition--,moveLength--; //从后面开始查找插入位置
for(int j=a.length-1;j>moveLength;j--) { a.elem[j+1]=a.elem[j]; //元素后移 } a.elem[insertPosition+1]=value; //插入值 a.length++; //长度+1 return OK; } //InsertOrder

3.数组A有m+n个元素,前m个和后n个元素均是有序,设计一个算法

使其有序

1.先比较m和n的数量,将数量较多的复制到数组头部(比如1,2,3,4,|5,8,)

2.按照InsertOrder方法,将数量少的部分重新插入数组(需要注意的是数组长度保持不变)

原文地址:https://www.cnblogs.com/Clingingboy/p/1910873.html