淺談順序存儲結構

存儲結構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
相關文章
相關標籤/搜索