浅谈顺序存储结构

存储结构ios

存储结构是什么?即在内存区域用怎样的存储方式,怎样的结构存储数据,把一百双鞋子比喻成数据元素,摆放鞋子的地方就是内存区域,而鞋子能够有不一样的摆法,怎样摆才能让人快速找到?编程

怎样摆才能容易拿(取)放(存)。在内存中,数据经过不一样的“摆法”,是为了减小内存占用或者更快存取。数组

顺序存储结构:编程语言

在内存中,分配出一块区域,将数据元素连续存储其中,按照必定的顺序,如:函数

int arrary []={1,2,3,4,5,6,}
  我定义了一个数组,就是在内存单元中开辟了一个存储区域,用于摆放上文提到的“鞋子”。一眼望去,这个数组有6个存储了元素的存储单元,对,他们紧挨着,就像邻居同样
从存储结构上讲,这就是顺序存储。arrary[0]是 1,它的隔壁不是老王,是 arrary[1],即 2;

如今有几个问题:spa

1.我怎么在内存区域中找到这个数组 (编程语言的知识)设计

2.个人数据元素为何要这样存储,有什么好处?3d

3.它的缺点是什么?指针

答:调试

1.众所周知,咱们在访问数组的时候,须要使用数组名,

好比我访问数组的第一个元素:arrary[0]

第二个元素:arrary[1];

好吧,这个很浅显,咱们在定义数组后,数组名能够理解为 是这个存储区域的地址,系统经过数组名(地址)找到了这个 块内存区域,

从我访问第一个元素和第二个元素能够看出,在线性存储结构中,我想读取元素是很容易的,对,这就是线性存储结构的优点所在

 

2. 上文其实已经提到,我访问其中的元素很容易,由于他们给了 固定连续的位置,如图

(图1 来源:百度图片)

图一,看起来就像大鞋柜,每一层都是固定的位置,我第一层就放 我常常穿的鞋子,第二层我就放 拖鞋......

每次我要拿的时候,我只要根据位置就能够了。

在上文的数组定义中,int 决定了这个大柜子里面装的是 int 型数据,系统会根据数据类型量身打造,分配能够存放该数据的内存空间,不会太大也不会过小。

你家的鞋柜会作得桌子也能放进去吗?显然没有,那多浪费空间,在内存存储中,第一咱们要快速存取,第二咱们要尽可能节省内存空间

总结:顺序存储结构:读取快,节省内存空间.

 

3.有利必有弊,在作这个柜子的时候,我设计为6层,但后来我买了10双鞋子,无处摆放了吧?

线性存储结构也是如此,当我定义了,它就只能按照当初定义时的大小,多出的东西没办法塞进去,就容易溢出了。

回过头来,2中咱们谈到它量身定作的属性,说它所以而节省内存空间,其实.....在实际应用中,我定义一个数组,为了不溢出状况,可能会尽可能使其分配足够的内存空间

int a[100]={10,20,30,40,};

但我实际就用了 4个存储单元,其它的就目前而言,空间浪费了

因此,它的一大缺点就是:有空间限制,当空间不够时,容易溢出,当元素个数远少于以前预分配的,形成空间浪费

调试一下看看:

先定义:

(图 2 )

观察:

(图3)

除了4个内存单元有 被赋值,其它尚未用到默认为0,但它确确实实占用你的内存呀!

还有,我如今不止要4个数据了 我要存1000个,存不进了吧

 

 

还有:从图3能够看到

a[0]=10; a[1]=20;a[2]=30;a[3]=40;

 

那么,我如今要在其中插入一个数,好比我要在a[1]这个位置插入15

插入后就是:

a[0]=10; a[1]=15;a[2]=20;a[3]=30;a[4]=40;

注意是 插入,不是把a[1]设置为15,因此原先数组用了 4个存储单元来存放元素,插入一个,如今要用到 5个

怎么作?:

先判断我这个数组是否是有足够的存储单元?我定义了100个,显然太够了

而后我插入的位置是否合理?我插入在a[1]这个位置,在数组中 逻辑位置 pos为2;它不是奇奇怪怪的a[-1]或者a[101],显然合理

那么就来插吧,首先我须要把原数组中,a[1]到a[4]中的元素都日后挪一个位置,这样才能空出一个单元来安放我要插入的元素:

如:

//前面省略若干啰里啰唆的代码
int item=15;//要插入的值为15 int pos=1;//要插入的物理位置为 a[1]; for(int i=4;i>=pos;i--) { a[i+1]=a[i]; } a[pos]=item; //终于把15插进去了

上面那个for循环干吗?

看看调试就知道了:

上车

(图4 我把数组改成 6 个单元了   为了方便)

(0)还没执行循环时:

(1)循环走一圈:

注意:a[3]=40,a[4]=40? 显然,该元素日后挪了一个位置

那两个相同怎么办?别急

(2)循环再走一圈:

如今是a[2]日后挪了一个位置 覆盖了原来的a[3]的值;

(....)通过循环以后:

如愿以偿。说白了,for循环里面的做用能够这样比喻:

一群人在排队,他是线性结构的,因此从第一我的到最后那个大兄弟的队伍是一条直线,

我想插队,在第2个位置插入,原先的老二到最后那个大兄弟是否是就得日后挪一个位置,

而上文的操做,是先让最后一个元素日后挪,而后倒数第二个元素也日后挪,

遍历循环下来,中间就空出一个位置,以便让我插入!

说了那么多,若是你还不懂,把文中的代码好好咀嚼一下 0_0

经过这个例子,能够得出:我就插入一个数,至于这么麻烦吗?

对,就是这么麻烦!

因此这也是顺序存储结构的另外一大缺点,插入麻烦!

数据操做,无非增删查改。

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

//listinarray.h
#include <iostream>
using namespace std;

#define MaxSize 100   

typedef int ElemType;//声明元素类型

typedef struct{     
    ElemType data[MaxSize]; //存放线性表数据
    int length;
}SqList;// SqList为用户定义的线性表类型


//初始化空线性表
void InitList(SqList &L);

//判断线性表是否为空 
int ListEmpty(SqList &L);

//求出线性表长度
int ListLength(SqList &L);

//向线性表指定位置插入一个新元素
int ListInsert(SqList &L, int pos, ElemType item);

//从线性表中删除第一个与指定值匹配的元素
int ListDelete(SqList &L, int pos, ElemType *item);

//获取顺序表中指定位置上的数据元素 
int GetElem(SqList &L,int pos,ElemType *item);

//从线性表中查找元素,返回第一个与指定值匹配元素位置
int Find(SqList &L,ElemType item);

//遍历输出线性表
int TraverseList(SqList &L);

//合并函数
int MergeList(SqList & L1,SqList L2);

 

 

 

//listinarray.cpp
#include "listinarray.h"

//初始化空线性表 
void InitList(SqList &L)
{
    L.length=0;
}

//判断线性表是否为空 
int ListEmpty(SqList &L)
{
    if(L.length<=0)    
        return 1;
    else    
        return 0;
} 

//求出线性表长度
int ListLength(SqList &L)
{
    return L.length;
}

//向线性表指定位置插入一个新元素
int ListInsert(SqList &L, int pos, ElemType item)
{//pos为插入的(逻辑)位置,item为待插入的数据元素
    int i;
    if(L.length>=MaxSize){                  //判表满
        cout<<"顺序表满,没法插入!"<<endl;
        return 0;}
    if(pos<=0 || pos>L.length+1){           //判位置
        cout<<"插入位置无效!"<<endl;
        return 0;}
    for(i=L.length-1;  i>=pos-1;  i--)     //向后移动元素
        L.data[i+1]=L.data[i];
    L.data[pos-1]=item;                    //插入    
    L.length++;                        //表长增一
    return 1; 
} 

//从线性表中删除第一个与指定值匹配的元素
int ListDelete(SqList &L, int pos, ElemType *item)
{//pos为删除的(逻辑)位置,用item返回被删元素
    int i;
    if(ListEmpty(L)){                     //判表空
        cout<<"顺序表为空表,没法删除!"<<endl;
        return 0; }
    if(pos<1 || pos>L.length){       //判位置
        cout<<"删除位置无效!"<<endl;
        return 0; }
    *item=L.data[pos-1];          //删除元素前,把元素的值经过指针传递给外部,备用
    for(i=pos;i<L.length;i++)      //向前移动元素    
          L.data[i-1]=L.data[i];
    L.length--;                   //表长减一
    return 1; 
}

//获取顺序表中指定位置上的数据元素 
int GetElem(SqList &L,int pos,ElemType *item)
{//pos为指定位置,item用于返回找到的数据元素if(ListEmpty(L))    return 0;
    if(pos<=0 || pos>L.length){
        cout<<"位置无效"<<endl;
        return 0;}
    *item=L.data[pos-1];        //把元素的值经过指针传递给外部
    return 1;
} 

//从线性表中查找元素,返回第一个与指定值匹配元素位置
int Find(SqList &L,ElemType item)
{//item为待查找的数据元素
    int i=0;   // i表示当前查找的位置,从头开始
    if(ListEmpty(L)){
        cout<<"顺序表为空表,没法查找!"<<endl;
        return 0;
    }
    //从头至尾比较线性表中的元素,当未超出线性表的末尾,且未找到时,i向后移
    while(i<L.length && L.data[i]!=item) 
        i++;
    if(i<L.length)        //若是未超出线性表的末尾,说明找到
        return i+1;     //返回逻辑位置
    else                
        return 0;       //超出线性表的末尾,则说明找不到
} 

//遍历输出线性表
int TraverseList(SqList &L)
{
    int i;
    for(i=0;i<L.length;i++)    //从头至尾输出线性表的每个元素
        cout<<L.data[i]<<"  ";
    cout<<endl;
    return 1;
}

//合并函数
int MergeList(SqList & L1,SqList L2)
{
    cout<<"线性表"<<L1<<"中有数据:"<<endl;
    TraverseList(L1);
    cout<<"线性表"<<L2<<"中有数据:"<<endl;

    for (int i =L1.length; i <L1.length+L2.length; i++) {
        ListInsert(L1,i,L2.data[i-L1.length]);
    }

}
 
//content.cpp
 
#include "listinarray.h"

int main()
{



    SqList my_List1,my_List2;//定义线性表SqList类型的变量
    ElemType Array[]={27,39,2,77,89,66};

    //初始化线性表
    InitList(my_List1);
    InitList(my_List2);

    //向线性表的指定位置插入数据
    ListInsert(my_List1,1,89);
    ListInsert(my_List1,1,77);
    ListInsert(my_List1,3,66);
    ListInsert(my_List1,1,2);
    ListInsert(my_List1,1,39);
    ListInsert(my_List1,1,27);

    for(int i=1; i<=10; i++)
    {
        ListInsert(my_List2,i,i);
    }
    for (int i = 1; i <=10; i++) {

        ListInsert(my_List2,11,i);
    }


    //输出线性表元素
    cout<<"my_list1:";
    TraverseList(my_List1);
    cout<<"my_list2:";
    TraverseList(my_List2);

    return 0;
}
 

 

 

 

 

 

 

 



by TL on 2017/10/4
相关文章
相关标签/搜索