線性表的順序存儲結(jié)構(gòu)

順序存儲定義

今天來總結(jié)一下線性表的順序存儲結(jié)構(gòu)拿诸。首先來看下順序存儲結(jié)構(gòu)的定義圃庭。

線性表的順序存儲結(jié)構(gòu)鹰溜,指的是用一段地址連續(xù)的存儲單元依次存儲線性表的數(shù)據(jù)元素序芦。

舉個簡單的例子愧沟,藺老師在給九班學生安排座位之前蔬咬,會讓學生們從矮到高按照身高的高矮升序排列,假如藺老師的班上只有十個學生沐寺,而全班共有50個座位林艘,那藺老師會把這10個學生,連續(xù)的安排在教室的前兩排之內(nèi)混坞,每個人都有自己的同桌狐援,連續(xù)的10個座位,那么這10個學生所占用的就是一片連續(xù)的座位。相當于內(nèi)存中有50個數(shù)據(jù)元素的空間啥酱,而10個學生只占用了中間的連續(xù)十個大小的空間场钉。

因為線性表中,存儲的數(shù)據(jù)元素的類型都相同懈涛,而存儲空間又是連續(xù)的逛万,那么我們可以用一維數(shù)組來實現(xiàn)線性表的存儲結(jié)構(gòu)。

因為班上一共有50個座位批钠,所以藺老師在安排座位時宇植,也沒必要一定從第一個座位開始安排,可以從第二排或者第三排來安排座位埋心,選定座位之后指郁,學生一個挨一個的坐進去就可以了。所以選定線性表時拷呆,在內(nèi)存中找一塊地闲坎,于是這塊地的第一個位置就非常關(guān)鍵,它為存儲空間的起始位置茬斧。

每天放學回家腰懂,藺老師會要求這10個學生排隊走出校門,而并不是每個學生每天都會上學项秉,比如彤彤這樣的學生绣溜,每天放學要去等藺老師下班,那么隊伍里可能只有九個人娄蔼,而這九個人還是排成了一列怖喻,誰在前誰在后關(guān)系依舊很明確,只是少了彤彤而已岁诉。而這個例子锚沸,就表示了線性表一一對應(yīng)的特點,就像排隊涕癣,在整隊的時候隨著每天的放學排隊哗蜈,大家很清楚自己該出現(xiàn)在哪個位置。

順序存儲結(jié)構(gòu)的代碼

我們來看線性表順序存儲結(jié)構(gòu)的結(jié)構(gòu)代碼:

#define MAXSIZE 10          //存儲空間的初始化分配

typedef int ElementType;    //定義線性表元素數(shù)據(jù)類型 這里假設(shè)為int

typedef struct
{
    ElementType data[MAXSIZE];      //線性表存儲數(shù)據(jù)元素
    
    int length;                     //線性表的長度
    
}SqList;

這里我們能看到順序存儲結(jié)構(gòu)所需要的三個屬性:

  • 存儲空間的起始位置:數(shù)組data属划,它的存儲位置就是存儲空間的存儲位置

  • 線性表的最大容量恬叹,數(shù)組長度MAXSIZE

  • 線性表的當前長度: length

我們對每個線性表位置的存入或取出的數(shù)據(jù),對于計算機來說都是相等的時間同眯,也就是一個常數(shù)绽昼。因此用上一次討論的算法時間復(fù)雜度的概念來說,線性表的時間復(fù)雜度為O(1)须蜗。我們通常把具有這一特點的存儲結(jié)構(gòu)稱為隨機存儲結(jié)構(gòu)硅确。

順序存儲結(jié)構(gòu)的插入或刪除

在討論順序存儲結(jié)構(gòu)的實現(xiàn)方式之前目溉,我們先來定義一下函數(shù)運行的狀態(tài)代碼,用來返回線性表運行的狀態(tài)菱农。

/**
 *  函數(shù)運行的狀態(tài)代碼
 *
 *
 */
#define SUCCESS 1
#define ERROR   0

typedef int Status;  //狀態(tài)代碼的類型

這段代碼我們定義了Status為狀態(tài)代碼的類型缭付,返回SUCCESS代表1,返回ERROR代表0循未。本文之后的所有狀態(tài)代碼就不再詳述了陷猫。

創(chuàng)建線性表(初始化)

在上面我們已經(jīng)定義好了線性表的屬性,并確定了線性表的最大存儲容量的妖,那么我們在剛開始時绣檬,對線性表進行初始化,創(chuàng)建一個線性表嫂粟。

/**
 線性表的初始化 并分配存儲單元
 
 - returns: SqList*
 */
SqList * initSqList()
{
    SqList * list = (SqList *)malloc(sizeof(SqList));
    
    list->length = 0 ;
    
    return list;
}

在這里我們還是用C語言來操作娇未,創(chuàng)建了一張線性表,用malloc分配存儲空間星虹,定義當前線性表長度為0零抬,最后返回值為本張線性表。

獲得元素操作
//獲取線性表中的元素
Status GetElem (SqList * L , int i , ElementType e)
{
    if (L->length == 0 || i < 1 || i > L->length ) {
        return ERROR;
    }
    
    e = L->data[i-1];
    return SUCCESS;
}

在獲取元素的操作中呢宽涌,我們定義了一個e平夜,用來返回L中第i個元素的值。

插入操作

在這里先不放代碼护糖,先來討論一下線性表的插入概念褥芒。比如我在火車站排隊等著取票嚼松,排了很久的隊終于快輪到我了嫡良,這時候有一個很漂亮的姑娘過來,可憐兮兮的對我說:帥哥献酗,我的車還有幾分鐘
就開了寝受,能讓我先取一下么『辟耍可能我會“以貌取人”很澄,答應(yīng)了這個漂亮姑娘的要求,于是這個姑娘排到了我的前面颜及,可是我畢竟有女朋友甩苛,再加上男女授受不親,我又不想回家跪鍵盤俏站,于是我得往后退一步讯蒲,讓出一個空間給姑娘排在我前面,我后面的人也得跟著我的步伐往后退一步肄扎。這時候墨林,就類似于線性表的插入算法的思路:

  • 如果插入的位置不合理赁酝,拋出異常

  • 如果線性表的長度大于數(shù)組長度,拋出異承竦龋或者動態(tài)增加存儲空間

  • 從最后一個元素酌呆,向前遍歷到第i個位置,分別將它們都向后移動一個位置搔耕。

  • 將要插入的元素插入到位置i

  • 表長+1

代碼的話隙袁,我用了兩種方式,一種是線性表以棧的方式加入數(shù)據(jù)元素弃榨,即為每一次都加在隊列的最后面藤乙,一種是按照要求,添加到指定的位置中惭墓。

棧的方式插入數(shù)據(jù)元素的實現(xiàn)代碼:

//線性表以棧的方式加入數(shù)據(jù)
Status pushElement(ElementType e, SqList * list)
{
    int length = list->length;
    if (length < 0 || length > MAXSIZE) {
        return ERROR;
    }
    
    list->data[length] = e;
    list->length++;
    
    return SUCCESS;
}

在指定位置插入數(shù)據(jù)元素的代碼實現(xiàn)如下:

/**
 *  在線性表中的第i個位置插入之前新的元素數(shù)據(jù)e坛梁,線性表的長度+1
 *
 */
Status insertElementWithLocation(ElementType e, SqList * list, int i)
{
    int k;
    //判斷線性表的存儲空間是否已滿
    if (list->length == MAXSIZE) {
        return ERROR;
    }
    
    //判斷i的合理性
    if (i < 1 || i > list->length) {
        return ERROR;
    }
    
    //將要插入的位置后面的數(shù)據(jù)向后移動一位
    if (i <= list->length) {
        for (k = list->length - 1; k >= i-1; k--) {
            list->data[k+i] = list->data[k];
        }
    }
    
    list->data[i-1] = e;  //插入新元素
    list->length++;
    return SUCCESS;
    
}
刪除操作

講完了插入的概念以及實現(xiàn)巧勤,應(yīng)該對刪除操作的行為也有了理解瓦呼,即為從指定位置,刪除需要刪除的元素氧映。

所以刪除算法的思路:

  • 如果刪除位置不合理钧萍,拋出異常

  • 取出刪除元素

  • 從刪除元素開始褐缠,之后的元素至最后一個元素的存儲位置向前挪動一個位置

  • 表長-1

我們同樣用棧的刪除模式和指定位置刪除的模式來實現(xiàn)代碼。

棧的方式刪除元素风瘦,即為每次都刪除最后一個元素的代碼實現(xiàn):

/**
 *  按照棧的方式刪除元素 e用來接收刪除出來的值
 */

Status popElement(ElementType e, SqList *list)
{
    int length = list->length;
    
    //判斷線性表的合法性
    if (length < 0 || length > MAXSIZE) {
        return ERROR;
    }
    
    e = list->data[length - 1];
    list->length -- ;
    return SUCCESS;
}

在指定位置刪除元素的代碼實現(xiàn)如下:


/**
 *  在線性表中的第i個位置刪除元素 線性表的長度減一
 */

Status deleteElementWithLocation(ElementType e, int i , SqList * list)
{
    //判斷線性表的合法性
    if (list->length < 0 || list->length > MAXSIZE ) {
        return ERROR;
    }
    
    //判斷刪除位置的合法性
    if (i < 1 || i > list->length) {
        return ERROR;
    }
    
    e = list->data[i-1];
    
    if (i < list->length) {
        //將刪除位置的后繼元素前移
        for (int k = i; k < list->length; k++) {
            list->data[k-1] = list->data[k];
        }
    }
    
    list->length -- ;
    
    return SUCCESS;
}
遍歷線性表

最后為了方便我們等下來驗證代碼的正確性队魏,我們寫一個函數(shù)來遍歷線性表,代碼如下:


/**
 *  遍歷線性表
 */

Status displayList(SqList * list)
{
    if (list->length < 0 || list->length > MAXSIZE) {
        return ERROR;
    }
    
    printf("***************************\n");
    
    for (int i = 0; i < list->length; i++) {
        printf("數(shù)值 = %d , 地址 = %p\n",list->data[i], &list->data[i]);
    }
    printf("***************************\n");
    
    return SUCCESS;
}
驗證代碼正確性

在驗證代碼的正確性時万搔,我用了Objective-C語言來寫胡桨,大體思路如果是使用C語言的程序員,也是能完全看懂的瞬雹。

我先創(chuàng)建了一個線性表昧谊,并且遍歷它,打印地址來驗證順序結(jié)構(gòu)存儲空間的連續(xù)性酗捌。


 //把1-8按順序入棧
        SqList * list = initSqList();

        NSLog(@"把1-8按順序入棧");
        int j = 1;
        for (int i = 0; i <8  ; i++) {
            pushElement(j, list);
            ++j;
        }

        displayList(list);

因為存儲空間總大小為10個元素單位呢诬,而我要求把1-8共8個數(shù)按順序存入線性表中。打印結(jié)果如下:

***************************
數(shù)值 = 1 , 地址 = 0x1002014d0
數(shù)值 = 2 , 地址 = 0x1002014d4
數(shù)值 = 3 , 地址 = 0x1002014d8
數(shù)值 = 4 , 地址 = 0x1002014dc
數(shù)值 = 6 , 地址 = 0x1002014e0
數(shù)值 = 7 , 地址 = 0x1002014e4
數(shù)值 = 8 , 地址 = 0x1002014e8
***************************

我們可以看到胖缤,數(shù)值以及存儲空間都是連續(xù)的尚镰,說明我們用棧的方式插入線性表是創(chuàng)建成功的。

我又要求往第八個位置插入724這個數(shù)字

        //往第8個位置插入724;
        
        insertElementWithLocation(724, list, 8);

運行結(jié)果如下哪廓,可以清楚的看到第八位是724狗唉,而原先的元素后移一位。

第八位增加724
***************************
數(shù)值 = 1 , 地址 = 0x100101320
數(shù)值 = 2 , 地址 = 0x100101324
數(shù)值 = 3 , 地址 = 0x100101328
數(shù)值 = 4 , 地址 = 0x10010132c
數(shù)值 = 5 , 地址 = 0x100101330
數(shù)值 = 6 , 地址 = 0x100101334
數(shù)值 = 7 , 地址 = 0x100101338
數(shù)值 = 724 , 地址 = 0x10010133c
數(shù)值 = 8 , 地址 = 0x100101340
***************************

驗證刪除操作的時候撩独,我們命令把第五位的數(shù)據(jù)刪除(以原始數(shù)據(jù)為例)

//        把第五位的數(shù)據(jù)刪除
        deleteElementWithLocation(0, 5, list);

得到結(jié)果如下:

刪除第五位
***************************
數(shù)值 = 1 , 地址 = 0x1002014d0
數(shù)值 = 2 , 地址 = 0x1002014d4
數(shù)值 = 3 , 地址 = 0x1002014d8
數(shù)值 = 4 , 地址 = 0x1002014dc
數(shù)值 = 6 , 地址 = 0x1002014e0
數(shù)值 = 7 , 地址 = 0x1002014e4
數(shù)值 = 8 , 地址 = 0x1002014e8
***************************

至此敞曹,我們可以得出結(jié)論我們創(chuàng)建的線性表是正確的账月,連續(xù)的,具備線性表的屬性的澳迫。而我們在對線性表的順序存儲結(jié)構(gòu)的插入和刪除的操作也是正確的局齿,實現(xiàn)了功能。所以今天的線性表的順序存儲結(jié)構(gòu)橄登,就講到這里抓歼,以上代碼我已經(jīng)上傳到Github上,若有講的不清楚的地方拢锹,也可以下載Github上的代碼來參考谣妻。

線性表的順序存儲結(jié)構(gòu)Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卒稳,隨后出現(xiàn)的幾起案子蹋半,更是在濱河造成了極大的恐慌,老刑警劉巖充坑,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件减江,死亡現(xiàn)場離奇詭異,居然都是意外死亡捻爷,警方通過查閱死者的電腦和手機辈灼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來也榄,“玉大人巡莹,你說我怎么就攤上這事√鹱希” “怎么了降宅?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長棵介。 經(jīng)常有香客問我钉鸯,道長,這世上最難降的妖魔是什么邮辽? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮贸营,結(jié)果婚禮上吨述,老公的妹妹穿的比我還像新娘。我一直安慰自己钞脂,他們只是感情好揣云,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冰啃,像睡著了一般邓夕。 火紅的嫁衣襯著肌膚如雪刘莹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天焚刚,我揣著相機與錄音点弯,去河邊找鬼。 笑死矿咕,一個胖子當著我的面吹牛抢肛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碳柱,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼捡絮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了莲镣?” 一聲冷哼從身側(cè)響起福稳,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瑞侮,沒想到半個月后灵寺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡区岗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年略板,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慈缔。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡叮称,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出藐鹤,到底是詐尸還是另有隱情瓤檐,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布娱节,位于F島的核電站挠蛉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肄满。R本人自食惡果不足惜谴古,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稠歉。 院中可真熱鬧掰担,春花似錦、人聲如沸怒炸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至勺疼,卻和暖如春教寂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背执庐。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工酪耕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耕肩。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓因妇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親猿诸。 傳聞我的和親對象是個殘疾皇子婚被,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容