數(shù)據(jù)結構C語言之線性表

發(fā)現(xiàn)更多計算機知識,歡迎訪問Cr不是鉻的個人網(wǎng)站

1.1線性表的定義

線性表是具有相同特性的數(shù)據(jù)元素的一個有限序列
對應的邏輯結構圖形:

file

從線性表的定義中可以看出它的特性:

(1)有窮性:一個線性表中的元素個數(shù)是有限的

(2)一致性:一個線性表中所有元素的性質相同,即數(shù)據(jù)類型相同

(3)序列性:各個元素的相對位置是線性的

1.2線性表的抽象數(shù)據(jù)類型描述

(如下圖所示)

file

那為什么要引進這個數(shù)據(jù)結構呢送巡?那就不得不談談它的作用了。

線性表的作用體現(xiàn)在兩個方面:

a. 當一個線性表實現(xiàn)后善茎,程序員加油直接使用它來存放數(shù)據(jù)缭召,即作為存放數(shù)據(jù)的容器

b.使用線性表的基本運算來完成更復雜的運算

2.1線性表的順序存儲結構——順序表

線性表的順序存儲結構簡稱為順序表

file

(如圖為線性表到順序表的映射)

需要注意的是順序表采用數(shù)組進行實現(xiàn)滋捶,但是不是任意數(shù)組可以作為一個順序表撞鹉,二者運算是不同的

下圖為順序表的存儲示意圖
file

2.2順序表的基本運算實現(xiàn)

(1)結構體SqList定義

//數(shù)據(jù)元素
typedef int ElemType;
//結構體
typedef struct
{
    ElemType data[MaxSize];
    //數(shù)據(jù)長度
    int length;
}SqList;

(2)建立順序表

//建立順序表
void CreateList(SqList*& L, ElemType a[], int n)
{
    int i = 0, k = 0;
    //記得一定要分配內存空間 
    L = (SqList*)malloc(sizeof(SqList));
    while (i < n)
    {
        //將a[i]存儲到L中
        L->data[k] = a[i];
        k++; i++;
    }
    L->length = k;
}

(3)初始化線性表

void InitList(SqList*& L)
{
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0; //置空線性表的長度為0
}

(4)銷毀線性表

void DestroyList(SqList*& L)
{
    free(L);//釋放L所指的順序表空間
}

(5)判斷是否為空

bool ListEmpty(SqList* L)
{
    return(L->length == 0);
}

(6)求線性表長度

int ListLength(SqList* L)
{
    return (L->length);
}

(7)求表中某個值

bool GetElem(SqList* L, int i, ElemType& e)
{
    if (i<1 || i > L->length)
        return false;
    e = L->data[i - 1];
    return true;    //成功找到元素返回true
}

(8)按照元素值查找

int LocateElem(SqList* L,ElemType e)
{
    int i = 0;
    while (i < L->length && L->data[i] != e)
        i++;
    if (i >= L->length)
        return 0;
    else
        return i + 1;       //返回邏輯序號
}

(9)輸出線性表

void DisplayList(SqList* L)
{
    for (int i = 0; i < L->length; i++)
        printf("%d", L->data[i]);
    printf("\n");
}

(10)完整代碼

#include<iostream>
using namespace std;
const int MaxSize = 1005;
typedef int ElemType;
typedef struct
{
    ElemType data[MaxSize];
    int length;
}SqList;

//建立順序表
void CreateList(SqList*& L, ElemType a[], int n)
{
    int i = 0, k = 0;
    //記得一定要分配內存空間 
    L = (SqList*)malloc(sizeof(SqList));
    while (i < n)
    {
        L->data[k] = a[i];
        k++; i++;
    }
    L->length = k;
}
//初始化線性表
void InitList(SqList*& L)
{
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0; //置空線性表的長度為0
}
void DestroyList(SqList*& L)
{
    free(L);//釋放L所指的順序表空間
}
bool ListEmpty(SqList* L)
{
    return(L->length == 0);
}

int ListLength(SqList* L)
{
    return (L->length);
}
void DisplayList(SqList* L)
{
    for (int i = 0; i < L->length; i++)
        printf("%d", L->data[i]);
    printf("\n");
}
bool GetElem(SqList* L, int i, ElemType& e)
{
    if (i<1 || i > L->length)
        return false;
    e = L->data[i - 1];
    return true;    //成功找到元素返回true
}
int LocateElem(SqList* L,ElemType e)
{
    int i = 0;
    while (i < L->length && L->data[i] != e)
        i++;
    if (i >= L->length)
        return 0;
    else
        return i + 1;       //返回邏輯序號
}
bool ListInsert(SqList*& L, int i, ElemType e)
{
    int j;
    if (i < 1 || i >L->length + 1 || L->length == MaxSize)
        return false;
    i--;
    for (j = L->length; j > i; j--)
        L->data[j] = L->data[j - 1];
    L->data[i] = e;
    L->length++;
    return true;
}
bool ListDelete(SqList*& L, int i, ElemType& e)
{
    int j;
    //特判是否符合 
    if (i < 1 || i>L->length)
        return false;
    i--;
    for (int j = i; j < L->length - 1; j++)
        L->data[j] = L->data[j + 1];
    L->length--;
    return true;
}
void delnodel(SqList*& L, ElemType x)
{
    int k = 0;
    for (int i = 0; i < L->length; i++)
        if (L->data[i] != x)
        {
            L->data[k] = L->data[i];
            k++;
        }
    L->length = k;
}

}
int main() {
    SqList* L;
    int a[10] = { 7,5,7,7,9,1,6,2,4,8 };
    CreateList(L, a, 10);

    DisplayList(L);
}

2.3線性表的鏈式存儲結構——鏈表

線性表的鏈式存儲就是鏈表疟丙,每個鏈表存儲點不僅包括數(shù)據(jù)域,還有指針域孔祸。

鏈表示意圖如下:

file

2.4 單鏈表算法實現(xiàn)

(1)數(shù)據(jù)結構聲明

typedef int ElemType;
typedef struct LinkNode
{
    ElemType data;      //存放元素值
    struct LinkNode* next;  //指向后繼結點

}LinkNode;

建立單鏈表有兩種方法:頭插法和尾插法

(2)頭插法

//建立單鏈表
void CreatListF(LinkNode*& L, ElemType a[], int n)
{
    LinkNode* s;
    //創(chuàng)建頭結點 
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL; //頭結點指針域置NULL
    for (int i = 0; i < n; i++)
    {
        s = (LinkNode*)malloc(sizeof(LinkNode));//重新分配空間
        s->data = a[i];
        s->next = L->next;
        L->next = s;
    }
}

(3)尾插法

void CreatListR(LinkNode*& L, ElemType a[], int n)
{
    LinkNode* s, * r;
    //創(chuàng)建頭結點
    L = (LinkNode*)malloc(sizeof(LinkNode));
    r = L;                      //r始終指向尾結點隆敢,初始時指向頭結點
    for (int i = 0; i < n; i++)
    {
        s = (LinkNode*)malloc(sizeof(LinkNode));//重新分配空間
        s->data = a[i];
        r->next = s;
        r = s;
    }
    //尾結點的nextt域置為NULL
    r->next = NULL;         
}

(4)初始化

void InitList(LinkNode*& L)
{
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL;
}

(5)銷毀表

void DestroyList(LinkNode*& L)
{
    LinkNode* pre = L, * p = L->next;   //pre指向p的前驅結點
    while (p != NULL)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);      //循環(huán)結束時p為NULL发皿,pre指向尾結點
}

(6)輸出表

void DispList(LinkNode* L)
{
    LinkNode* p = L->next;//指向頭結點
    while (p!=NULL)
    {
        printf("%d", p->data);
        p = p->next;
    }
    printf("\n");
}

重點4藁邸!穴墅!

(7)鏈表的插入

bool ListInsert(LinkNode*& L, int i, ElemType e)
{
    int j = 0;
    LinkNode* p = L, * s;
    if (i <= 0)return false;//首結點的次序是一
    while (j < i - 1 && p != NULL)//找到第i-1個結點
    {
        j++;
        p = p->next;
    }
    if (p == NULL)
        return false;
    else
    {
        s = (LinkNode*)malloc(sizeof(LinkNode));
        //典中典
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
}

(8)刪除某個元素

bool ListDelete(LinkNode*& L, int i, ElemType& e)
{
    int j = 0;
    LinkNode* p = L, * q;
    if (i <= 0)return false;//頭結點是不計入其中的
    while (j < i - 1 && p != NULL)
    {
        j++;
        p = p->next;
    }       
    if (p == NULL)
        return false;
    else {
        q = p->next;
        if (q == NULL)
            return false;
        e = q->data;
        p->next = q->next;
        free(q);
        return true;
    }
}

最后介紹一下雙鏈表

2.5雙鏈表

(1)建立雙鏈表

typedef int ElemType;
// 定義DlinkNode結構體
struct DlinkNode {
    int data;           // 數(shù)據(jù)域
    DlinkNode* prior;   // 前驅指針
    DlinkNode* next;    // 后繼指針
};

同樣的惶室,雙鏈表的建立也有頭插法和尾插法

(2)頭插法

// 定義CreateListF函數(shù)
void CreateListF(DlinkNode*& L, ElemType a[], int n)
{
    DlinkNode* s;
    L = (DlinkNode*)malloc(sizeof(DlinkNode)); // 創(chuàng)建頭結點
    L->prior = L->next = NULL; // 先后指針域置NULL
    for (int i = 0; i < n; i++) // 循環(huán)創(chuàng)建數(shù)據(jù)結點
    {
        s = (DlinkNode*)malloc(sizeof(DlinkNode)); // 創(chuàng)建數(shù)據(jù)結點s
        s->data = a[i];
        s->next = L->next; // 將S插到頭結點之后
        if (L->next != NULL)
            L->next->prior = s;
        L->next = s;
        s->prior = L;
    }
}

(3)尾插法

void CreateListR(DlinkNode*& L, ElemType a[], int n)
{
    DlinkNode* s,*r;
    L = (DlinkNode*)malloc(sizeof(DlinkNode)); // 創(chuàng)建頭結點
    r = L;          //r始終指向尾結點温自,開始時指向頭結點
    for (int i = 0; i < n; i++) // 循環(huán)創(chuàng)建數(shù)據(jù)結點
    {
        s = (DlinkNode*)malloc(sizeof(DlinkNode)); // 創(chuàng)建數(shù)據(jù)結點s
        s->data = a[i];
        r->next = s; s->prior = r;      //將s結點插入到r結點之后
        r = s;                          //r指向尾結點
    }
    r->next = NULL;
}

2.6總結

線性表是一種基礎且重要的數(shù)據(jù)結構,常見的線性表有三種實現(xiàn)方式:順序表、單鏈表和雙鏈表皇钞。

本文對這三種線性表的實現(xiàn)方式及特點做一個簡要總結:

一悼泌、順序表順序表是將邏輯順序上相鄰的數(shù)據(jù)元素存儲在物理位置上也相鄰的存儲單元中,通常使用數(shù)組來實現(xiàn)。- 特點:定位直接,通過下標操作即可快速訪問任一位置的節(jié)點;實現(xiàn)簡單夹界。

缺點:插入刪除需要移動大量元素,效率低;存儲空間固定,擴容不靈活馆里。

二、單鏈表單鏈表通過鏈式存儲結構實現(xiàn),每個節(jié)點除存儲數(shù)據(jù)外,還儲存下一個節(jié)點的地址信息可柿。

-特點:存儲靈活,可動態(tài)擴展,插入刪除簡單,效率高鸠踪。-

缺點:訪問任一節(jié)點需要從頭結點遍歷,無法直接定位

三琴儿、雙鏈表雙鏈表相比單鏈表,每個節(jié)點增加一個指向前驅節(jié)點的指針,實現(xiàn)雙向鏈表负间。-

特點:可雙向遍歷鏈表,操作更靈活淀歇。-

缺點:每個節(jié)點存儲空間略大于單鏈表娇掏。

**綜上,三種線性表各有特點,使用需根據(jù)具體場景需求選擇合適的數(shù)據(jù)結構蕴轨。順序表操作簡單,鏈表存儲靈活,雙鏈表可以雙向訪問限府。開發(fā)時需要權衡效率與實現(xiàn)難度,選擇最優(yōu)實現(xiàn)读拆。**

本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布祠肥!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末痢虹,一起剝皮案震驚了整個濱河市被去,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奖唯,老刑警劉巖编振,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異臭埋,居然都是意外死亡踪央,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門瓢阴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來畅蹂,“玉大人,你說我怎么就攤上這事荣恐∫盒保” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵叠穆,是天一觀的道長少漆。 經(jīng)常有香客問我,道長硼被,這世上最難降的妖魔是什么示损? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮嚷硫,結果婚禮上检访,老公的妹妹穿的比我還像新娘始鱼。我一直安慰自己,他們只是感情好脆贵,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布医清。 她就那樣靜靜地躺著,像睡著了一般卖氨。 火紅的嫁衣襯著肌膚如雪会烙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天筒捺,我揣著相機與錄音持搜,去河邊找鬼。 笑死焙矛,一個胖子當著我的面吹牛葫盼,可吹牛的內容都是我干的。 我是一名探鬼主播村斟,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼贫导,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蟆盹?” 一聲冷哼從身側響起孩灯,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逾滥,沒想到半個月后峰档,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡寨昙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年讥巡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舔哪。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡欢顷,死狀恐怖,靈堂內的尸體忽然破棺而出捉蚤,到底是詐尸還是另有隱情抬驴,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布缆巧,位于F島的核電站布持,受9級特大地震影響,放射性物質發(fā)生泄漏陕悬。R本人自食惡果不足惜题暖,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芙委,春花似錦逞敷、人聲如沸狂秦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裂问。三九已至侧啼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間堪簿,已是汗流浹背痊乾。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留椭更,地道東北人哪审。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像虑瀑,于是被迫代替她去往敵國和親湿滓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內容