存儲結構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