存储结构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