#P2003. 数据结构.顺序表

数据结构.顺序表

1.定义

顺序表是顺序存储方式,即逻辑上相邻的数据在计算机内的存储位置也是相邻的。在顺序存储方式中,元素存储是连续的,中间不允许有空,可以快速定位某个元素,但是插入、删除时需要移动大量元素。根据分配空间方法的不同,顺序表可以分为静态分配和动态分配两种。

2.例子

有 n 个同学,陈老师把他们排成一队,并且知道他们每一个人站的位置,这些信息都记录在一张表格上。级长黄老师拿着这个表格,他能清楚的知道第 i 个人是谁,也能知道队列中某一个范围(从第 i 个人到第 j 个人)是哪些同学。我们用 c++ 程序来表示这个表格,可以是下面的这个程序:

int n;
string name[101];
int id[101];
cin>>n;
for(int i=1;i<=n;i++)
    cin>>name[i]>>id[i]; //输入队列中各个人的名字和学号

在上面的这个例子中,我们把各位同学的姓名和学号分别存入了 name 数组和 id 数组。数组的元素都是连续被使用的,中间没有跳过任何一个存储单元,n 个同学,两个数组都用了 n 个存储单元。

3.顺序表的操作

3.1 顺序表的取值(直接访问)

我们通过访问 name[i] 和 id[i] 就可以直接获得第 i 为同学的姓名和学号信息了。而且,数组元素 i+1 就代表第 i 位同学后面的那一位同学的信息,彼此之间的关系也是明确的。

\\我想知道第 7 位同学的姓名和学号
cout<<name[7]<<" "<<id[7]<<endl;

3.2 查询

假如级长黄老师想知道队伍里面是否有一个叫 邓强 的同学,他就要把表格过一遍。当然,如果有邓强,而且邓强排在第一位,那么黄老师一眼就知道结果了。但是,假设队伍里面么有邓强,或者邓强是在队伍很后的位置,那么黄老师就要看完整个表格或者几乎看完整个表格才知道答案。

bool Found = false
for(int i=1;i<=n;i++)
{
    if(name[i]=="邓强")
    {
        cout<<"找到了,他是队伍里的第"<<i<<"个同学"<<endl;
        Found = true;
        break;
    }
}
if(!Found) cout<<"找遍了整个表格都没看到有叫邓强的同学"<<endl;

3.3 删除

假设队列中的 陈亮 同学有事,要离开队列。他走了,我们要更新上述的这个表格的信息,这就是顺序表的删除操作。我们要做把陈平后面的人全部往前挪一个位置。只有这样,这个表格的信息才是准确的,级长黄老师看着表格才不会搞错。

\\先找到陈亮同学的位置
for(int i=5;i<n;i++)
{
    if(name[i]=="陈亮")
    {
        //陈亮的位置是 i ,要从 i+1 开始,把后面的人往前挪动
        for(int j=i;j<n;j++)
        {
            name[j] = name[j+1];
            id[j] = id[j+1];            
        }
        break;
    }
}
n -= 1; //队列的人数要减少

3.4 插入

假设这时候来了一个新同学 张鹏 ,陈老师要把张鹏插入到第 陆飞 的前面。 则从 陆飞 开始的同学都要先往后走一步,腾出个位置出来,然后张鹏再插入到这个位置。这个事情也是要在表格里面更新才行的,否则级长黄老师会搞错都。

//找陆飞的位置
for(int i=1;i<=n;i++)
{
    if(name[i]=="陆飞")
    {
        // 陆飞后面的人往后挪动一步
        for(j=n;j>i;j--)
        {
            name[j+1] = name[j];
            id[j+1] = id[j];
        }

        name[i+1] = "张鹏";
        id[i+1] = 278128; //假设张鹏的学号是 278128
    }
}
n++;

4. 总结

顺序表的存储方式在查询的时候比较快。但是,如果数据的查找、插入、删除都比较费劲。

顺序表特点

PS: 上述的时间复杂度描述中,数据的删除、插入 操作不包括先找到数据位置(删除哪一个数据,插入数据到什么位置)。