計(jì)算機(jī)編程內(nèi)功修練 --> 數(shù)據(jù)結(jié)構(gòu)之單鏈表

前言

上篇文章學(xué)習(xí)了線性表的順序存儲結(jié)構(gòu),不過,在代碼的實(shí)現(xiàn)過程中,發(fā)現(xiàn)了順序表的一個很大的問題:插入和刪除需要移動大量的數(shù)據(jù)元素,那如何解決這個問題?

鏈?zhǔn)酱鎯Y(jié)構(gòu)

前篇文章有談到過線性表的存儲方式绢掰,一種是順序存儲結(jié)構(gòu),另一種是鏈?zhǔn)酱鎯Y(jié)構(gòu)童擎。我們再來回顧一下鏈?zhǔn)酱鎯Φ亩x

為了表示每個數(shù)據(jù)元素與其直接后繼元素之間的邏輯關(guān)系滴劲,每個元素除了存儲本身的信息外,還需要存儲指示其直接后繼的信息

鏈?zhǔn)酱鎯Y(jié)構(gòu).png

單鏈表

上面的定義有提到邏輯關(guān)系顾复,有一種常見的鏈?zhǔn)酱鎯壿嫿Y(jié)構(gòu)可以體現(xiàn):單鏈表班挖。

n個結(jié)點(diǎn)鏈接成一個鏈?zhǔn)骄€性表的結(jié)構(gòu)叫做鏈表,當(dāng)每個結(jié)點(diǎn)中包含一個指針域時芯砸,叫做單鏈表

鏈表.png

鏈表的基本概念

上面的定義有提到鏈表萧芙,一個鏈表一般可以分為三個部分:

  • 表頭結(jié)點(diǎn)

    鏈表中的第一個結(jié)點(diǎn),包含指向第一個數(shù)據(jù)元素的指針以及鏈表自身的一些信息

  • 數(shù)據(jù)結(jié)點(diǎn)

    鏈表中代表數(shù)據(jù)元素的結(jié)點(diǎn)假丧,包含指向下一個數(shù)據(jù)元素的指針和數(shù)據(jù)元素的信息

  • 尾結(jié)點(diǎn)

    鏈表中的最后一個數(shù)據(jù)結(jié)點(diǎn)双揪,其下一個元素指針為空,也就是指針域?yàn)榭瞻悖硎緹o后繼

單鏈表結(jié)構(gòu)圖

單鏈表.png

實(shí)現(xiàn)單鏈表

在頭文件中聲明需要實(shí)現(xiàn)單鏈表的操作

typedef void LinkList;
typedef struct _tag_LinkListNode LinkListNode;
/**在C語言中可以用結(jié)構(gòu)體來定義鏈表中指針域*/
struct _tag_LinkListNode {

    /**指向下個元素的指針*/
    LinkListNode *next;
};

/**數(shù)據(jù)元素結(jié)點(diǎn)*/
typedef struct Value {

    LinkListNode next;
    int value;
} TValue;

LinkList *createLinkList();

void destroyLinkList(LinkList *list);

void clearLinkList(LinkList *list);

int getLinkListLen(LinkList *list);

int addLinkListEle(LinkList *list, LinkListNode *node, int position);

LinkListNode *getLinkListEle(LinkList *list, int position);

LinkListNode *deleteLinkListEle(LinkList *list,int position);

在實(shí)現(xiàn)的文件中定義頭節(jié)點(diǎn)

/**
 * 定義表頭結(jié)點(diǎn)
 */
typedef struct _tag_LinkList {

    /**指向第一個元素的頭指針*/
    LinkListNode header;
    /**整個單鏈表的長度*/
    int length;

} TLinkList;

單鏈表的添加元素操作

/**
 * 添加元素到單鏈表中指定位置
 * @param list
 * @param node
 * @param position  在鏈表中的索引值
 * @return
 */
int addLinkListEle(LinkList *list, LinkListNode *node, int position) {

    TLinkList *linkList = (TLinkList *) list;
    /**判斷單鏈表渔期、插入的元素以及插入的位置的合法性*/
    int ret = (linkList != NULL) && (node != NULL) && (position >= 0);
    int i;
    if (ret) {
        /** step 1 開始位置指向表頭*/
        LinkListNode *current = (LinkListNode *) linkList;
        for (i = 0; i < position && current->next != NULL; i++) {

            /**
             * step 2 由表頭開始通過next指針移動position次
             * 第position處的下一個元素就是要插入的位置,也就
             * 是當(dāng)前元素的current->next。
             */
            current = current->next;
        }
        /**
         * step 3 交換當(dāng)前元素和插入元素的指針域
         * 注:這兩步順序不能搞反疯趟,否則會導(dǎo)致單鏈
         * 表斷鏈
         */
        node->next = current->next;
        current->next = node;

        /**更新單鏈表長度*/
        linkList->length++;
    }
    return ret;
}

這里的核心算法就是step 2和step 3這兩步拘哨。我們可以通過圖來加深理解。請注意圖中的第2步與第1步是順序是不能搞反的信峻,否則會導(dǎo)致斷鏈

插入.png

單鏈表的刪除元素操作

/**
 * 刪除鏈表中指定的元素
 * @param list
 * @param position  被刪除元素在鏈表中的索引值
 * @return
 */
LinkListNode *deleteLinkListEle(LinkList *list, int position) {

    TLinkList *linkList = (TLinkList *) list;
    LinkListNode *node = NULL;
    if (linkList != NULL && position >= 0 && position < linkList->length) {

        LinkListNode *current = (LinkListNode *) linkList;
        /**獲取第position處元素倦青,該元素的next指針域就是需要刪除的元素*/
        for (int i = 0; i < position; i++) {
            current = current->next;
        }
        node = current->next;
        current->next = node->next;
        linkList->length--;

    }
    return node;
}
刪除.png

獲取元素

/**
 * 獲取指定位置的元素
 * @param list
 * @param position 被獲取元素在鏈表中的索引值
 * @return
 */
LinkListNode *getLinkListEle(LinkList *list, int position) {

    TLinkList *linkList = (TLinkList *) list;
    LinkListNode *node = NULL;
    int i;
    if (linkList != NULL && position >= 0 && position < linkList->length) {

        /** step 1 開始位置指向表頭*/
        LinkListNode *current = (LinkListNode *) linkList;

        for (i = 0; i < position; i++) {

            /** step 2 由表頭開始通過next指針移動position次*/
            current = current->next;

        }
        /** step 3 當(dāng)前元素的next指針即指向要獲取的元素*/
        node = current->next;
    }
    return node;
}

總結(jié)

單鏈表的一些主要操作就都已經(jīng)實(shí)現(xiàn)完了,代碼中注釋很清楚盹舞,再加上圖一起來理解就更非常容易了(完整代碼)产镐。那它與上篇文章學(xué)過的順序表有哪些優(yōu)缺點(diǎn)了?

  • 優(yōu)點(diǎn):

    • 無需一次性定制鏈表的容量
    • 插入和刪除無需移動數(shù)據(jù)元素
  • 缺點(diǎn)

    • 數(shù)據(jù)元素必須保存后繼元素的位位置信息
    • 獲取指定數(shù)據(jù)的元素操作需要順序訪問之前的元素
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矾策,一起剝皮案震驚了整個濱河市磷账,隨后出現(xiàn)的幾起案子峭沦,更是在濱河造成了極大的恐慌贾虽,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吼鱼,死亡現(xiàn)場離奇詭異蓬豁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)菇肃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門地粪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琐谤,你說我怎么就攤上這事蟆技。” “怎么了斗忌?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵质礼,是天一觀的道長。 經(jīng)常有香客問我织阳,道長眶蕉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任唧躲,我火速辦了婚禮造挽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弄痹。我一直安慰自己饭入,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布肛真。 她就那樣靜靜地躺著谐丢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪毁欣。 梳的紋絲不亂的頭發(fā)上庇谆,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天岳掐,我揣著相機(jī)與錄音,去河邊找鬼饭耳。 笑死串述,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的寞肖。 我是一名探鬼主播纲酗,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼新蟆!你這毒婦竟也來了觅赊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤琼稻,失蹤者是張志新(化名)和其女友劉穎吮螺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帕翻,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸠补,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘀掸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片紫岩。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖睬塌,靈堂內(nèi)的尸體忽然破棺而出泉蝌,到底是詐尸還是另有隱情,我是刑警寧澤揩晴,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布勋陪,位于F島的核電站,受9級特大地震影響文狱,放射性物質(zhì)發(fā)生泄漏粥鞋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一瞄崇、第九天 我趴在偏房一處隱蔽的房頂上張望呻粹。 院中可真熱鬧,春花似錦苏研、人聲如沸等浊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筹燕。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撒踪,已是汗流浹背过咬。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留制妄,地道東北人掸绞。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像耕捞,于是被迫代替她去往敵國和親衔掸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354

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