数据结构与算法之美(笔记1)数组

随机访问

链表适合插入,删除,时间复杂度是O(1),数组支持随机访问,根据下标随机访问的时间复杂度是O(1)。

插入,删除

插入操作

假设数组的长度为 n,现在,如果我们需要将一个数据插入到数组中的第K个位置。为了把第K个位置腾出来,我们需要把 k后的 n-k  位置顺序向后移动一位。

最好时间复杂度:在最后一位插入,时间复杂度为:O(1)。

最坏时间复杂度:在第一位插入,时间复杂度是:O(n)。

平均时间复杂度:我们有可能在n个位置插入,每一种情况的可能都是1/n,所以平均情况时间复杂度为 (1+2+…n)/n=O(n)。

如果数组中的数据是有序的,我们在某个位置插入一个新的元素时,就必须按照刚才的方法搬移 k 之后的数据。但是,如果数组中存储的数据并没有任何规律,数组只是被当作一个存储数据的集合。那么这种情况之下,我们可以把插入的数据放到数组的最后一位,然后与第K个位置进行交换,这样就把时间复杂度降到O(1)了。

删除操作

与插入一样,我们删除数据之后,也要搬移数据。

最好时间复杂度:在末位进行删除,O(1)。

最坏时间复杂度:搬移n-1个位置,O(n)。

平均时间复杂度:与插入类似,时间复杂度为O(n)。

优化:在某些情景下,我们可以将多次删除操作在一起执行,删除的效率会提高。我们先记录下已经删除的数据,当数组没有空间储存的时候,再触发一次真正的数据搬移。

容器与数组

1.如果特别关注性能,首选数组。

2.如果数据的大小已经事先知道,优先使用数组。

3.二维矩阵,使用数组更加直观。

 

如何实现一个动态扩容的数组?

我们事先给数组指定一个大小size,并且通过一个used表示已经使用了的数量,当used大于等于size的时候,我们就把size扩大两倍。这里我们需要一个size*2的数组,然后把之前的数组复制到这个扩大之后的数组。它的均摊时间复杂度是O(1)。

这里是c++代码实现:

#include <iostream>
using namespace std;

class array
{
private:
    int* arr;
    int capacity;
    int used;

public:
    array(int size){
        if(size == 0){
            size = 1;
        }
        arr = new int[size];
        capacity = size;
        used = 0;
    }
    void print(){
        for(int i=0;i<used;++i){
            cout << arr[i] << " " << endl;
        }
    }
    // 末位添加数据
    void append(int data){
        if(capacity <= used){
            int* temp = new int[capacity*2];
            for(int i=0;i<used;++i){
                temp[i] = arr[i];
            }
            arr = temp;
        }
        arr[used++] = data;
    }
};

测试代码:

#include <array.h>

int main(){
    array a(0);
    a.append(10);
    a.append(9);
    a.print();
}

如何实现合并两个有序的数组,成为一个有序的数组?

思路是这样的:假设第一个数组L1有m个数据,第二个数组L2有n个数据,我们创建一个新的,大小为m+n的数组,用两个游标 i和 j 遍历L1和L2,两个数组的数据每一次都相互比较一次,把小的放到新的数组,然后对应的游标向右移动,直到某个游标到达界限,这时候我们再判断哪个数组还没有遍历完,然后将剩下的数据复制到新的数组之中就可以了。它的时间和空间复杂度都是O(n)。

这里是代码实现:

int main(){

    int L1[5] = {1,3,5,7,9};
    int L2[6] = {2,4,6,8,10,12};

    int L3[11] = {0};

    int i=0,j=0,k=0;
    while(i < 5 && j < 6){
        if(L1[i] < L2[j]){
            L3[k++] = L1[i++];
        }else{
            L3[k++] = L2[j++];
        }
    }

    if(i<5){
        for(;i<5;++i){
            L3[k++] = L1[i];
        }
    }else{
        for(;j<6;++j){
            L3[k++] = L2[j];
        }
    }

    for(int i=0;i<11;++i){
        cout << L3[i] << " " << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42073553/article/details/88383357
今日推荐