国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結構】——單鏈表的基本操作(帶頭結點)

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結構】——單鏈表的基本操作(帶頭結點)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1.單鏈表的定義

? ? ? ? 單鏈表解決了順序表需要大量連續(xù)存儲單元的缺點,但單鏈表附加指針域,存儲密度較順序表低(考點?。。?/span>。由于單鏈表的元素離散地分布在存儲空間中,所以單鏈表是非隨機存取的存儲結構,即不能直接找到表中某個特定的結點。當查找某個特定結點時,需要從表頭開始遍歷。

????????通常使用頭指針來標識一個單鏈表,如單鏈表L,頭指針為NULL時表示一個空表。為了操作上的方便,可以在單鏈表的第一個結點之前附加一個頭結點。頭結點一般不存儲數(shù)據(jù),它的數(shù)據(jù)域可以不設任何信息,或記錄表長等信息;頭結點的指針域指向線性表的第一個元素結點。

為什么要引入頭結點呢?

引入頭結點后,可以帶來兩個優(yōu)點

①由于第一個數(shù)據(jù)結點的位置被存放在頭結點的指針域中,因此在鏈表第一個位置上的操作和在表的其他位置上的操作一致,無須進行特殊處理。

②無論鏈表是否為空,其頭指針都是指向頭結點的非空指針(空表中頭結點的指針域為空),因此空表和非空表的操作也得到了統(tǒng)一。

單鏈表的結點類型定義

typedef int ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

關于定義的幾點說明:

1.在單鏈表的定義中不能省略結構體名稱LNode(第2行中)。原因:在該結構體內部使用到了該結構體類型去定義next指針域。

2.第5行中的重命名LNode和*LinkList的意義:

這里相當于以下兩句:

typedef struct LNode LNode;//將結構體重命名為LNode
typedef struct LNode *LinkList;//將結構體的指針重命名為LinkList
LNode和LinkList的區(qū)別:
  1. LNode是一個具象的結構體類型,指向的是包含某個數(shù)據(jù)類型的數(shù)據(jù)域和指針域的結構體類型。
  2. 而LinkList是LNode的指針類型,它占用一定的內存空間,內存空間中存放的值是一個LNode類型結構體的地址。

2.單鏈表的基本操作實現(xiàn)

(1)頭插法建立單鏈表

LinkList list_head_insert(LinkList &L)
{
    L = (LinkList)malloc(sizeof(LNode));//申請頭節(jié)點空間
    L->next=NULL;
    ElemType x;
    scanf("%d", &x);
    LNode* s;//用來指向申請的新節(jié)點

    while(x!=9999)//輸入9999表示結束
    {
        s=(LinkList)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;//s的next指向原本鏈表的第一個節(jié)點
        L->next = s;
        scanf("%d", &x);
    }
    return L;
}

【注】:這里有一個常見的錯誤:分配結點空間的語句

L = (LinkList)malloc(sizeof(LNode));

錯誤寫法L = (LinkList)malloc(sizeof(LinkList));

要謹記:LinkList是LNode的指針類型,不代表結構體(該指針一般占用8個字節(jié)的空間)而這里需要的是分配的LNode大小的空間。

頭插法建立單鏈表 時間復雜度分析

采用頭插法建立單鏈表時,讀入數(shù)據(jù)的順序與生成的鏈表中的元素順序相反。每個結點插入的時間為O(1),設單鏈表長為n,則總時間復雜度為O(n).

(2)尾插法建立單鏈表?

尾插法的特點:

始終存在一個尾指針r指向鏈表的尾部,且讀入數(shù)據(jù)的順序與生成鏈表中元素的順序相同。

LinkList list_tail_insert(LinkList &L)
{
    L = (LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    ElemType x;
    scanf("%d", &x);
    LNode *s, *r=L;//s用來指向申請的新節(jié)點,r始終指向鏈表尾部
    while(x!=9999)//輸入9999表示結束
    {
        s = (LinkList) malloc(sizeof(LNode));
        s->data = x;
        r->next = s;//新節(jié)點給尾節(jié)點的next指針
        r=s;//r要指向新的尾部
        scanf("%d", &x);
    }
    r->next = NULL;//讓尾節(jié)點為Null
    return L;
}

尾插法建立單鏈表的時間復雜度分析?

?尾插法的時間復雜度與頭插法相同,都是O(n)。

?(3)按位查找結點

//按位置查找
LNode* GetElem(LinkList L, int SearchPos)
{
    int i=0;
    if(SearchPos<0)
    {
        return NULL;
    }
    while(i<SearchPos && L!=NULL)
    {
        L=L->next;
        i++;
    }
    return L;
}

?按位查找的時間復雜度

按位查找的時間復雜度為:O(n)

(4)按值查找

LNode *LocateElem(LinkList L, ElemType e)
{
    LNode *p = L->next;
    while(p!=NULL && p->data!=e)
        p = p->next;
    return p;
}

?按值查找的時間復雜度?

按值查找的時間復雜度為:O(n)

(5)在第i個位置上插入結點?

LinkList ListFrontInsert(LinkList L, int InsertPos, ElemType InsertVal)//注意:插入不會改變鏈表的頭節(jié)點(指針)L,和順序表不同,這里的形參不需要使用&
{
    LinkList p = GetElem(L, InsertPos-1);//GetElem函數(shù)中已自帶InsertPos-1是否合法的檢查
    if(NULL==p)
        return false;
    LinkList q;
    q = (LNode*) malloc(sizeof (LNode));
    q->data = InsertVal;
    q->next = p->next;//①
    p->next = q;//②
    return L;
}

?【注】:①②兩句的順序不能顛倒!(代碼的第9和第10行)

插入結點的時間復雜度分析

插入算法的主要時間開銷在于查找第i-1個元素,時間復雜度為O(n)。

若在給定的結點后面插入新結點,則時間復雜度僅為O(1).

【注】:在單鏈表的插入操作中,不會改變頭結點指針L,因此不需要使用&類型(這一點與順序表不同,順序表的插入操作會改變整個表,在順序表的插入函數(shù)中形參需要使用&)

(6)刪除結點操作

//刪除第i個位置的元素
bool ListDelete(LinkList L, int i) 
{
    LinkList p= GetElem(L, i-1);
    if(NULL==p)
    {
        return false;
    }
    LinkList q = p->next;
    //這里可能會有疑問,如果不定義指針q,用p->next=p->next->next可以嗎
    //這樣是不行的,因為被刪除的節(jié)點沒有了指針指向,無法free
    p->next = q->next;//斷鏈
    free(q);//釋放被刪除節(jié)點的空間
}

【注】:在刪除節(jié)點操作中,需要定義兩個指針p和q,p指向刪除位置i的前一個位置的結點,p指向需要被刪除的結點。這里可能會產生疑問,為什么一定要定義指針q呢?用語句p->next=p->next->next不是也可以達到刪除節(jié)點的效果嗎?

原因:這樣是不好的!如果不定義指針q,在p->next=p->next->next之后就無法再找到刪除的結點空間,無法free掉這塊空間。一般前面使用malloc分配的空間在后面使用完成后都需要free掉。

刪除結點的時間復雜度分析

刪除結點算法的時間開銷也主要在于查找第i-1個元素,時間復雜度為O(n).

整體代碼演示

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

//頭插法新建鏈表
LinkList list_head_insert(LinkList &L)
    L = (LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    ElemType x;
    scanf("%d", &x);
    LNode* s;//用來指向申請的新節(jié)點

    while(x!=9999)//輸入9999表示輸入結束
    {
        s=(LinkList)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;//s的next指向原本鏈表的第一個節(jié)點
        L->next = s;
        scanf("%d", &x);
    }
    return L;
}

//尾插法新建鏈表
//尾插法的特點:定義一個尾指針r總指向鏈表的尾部
LinkList list_tail_insert(LinkList &L)
{
    L = (LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    ElemType x;
    scanf("%d", &x);
    LNode *s, *r=L;//s用來指向申請的新節(jié)點,r始終指向鏈表尾部
    while(x!=9999)
    {
        s = (LinkList) malloc(sizeof(LNode));
        s->data = x;
        r->next = s;//新節(jié)點給尾節(jié)點的next指針
        r=s;//r要指向新的尾部
        scanf("%d", &x);
    }
    r->next = NULL;//讓尾節(jié)點為Null
    return L;
}

//鏈表打印
void print_list(LinkList L)
{
    L = L->next;//沒有使用引用,外面的L不會發(fā)生改變
    while(L!=NULL)
    {
        printf("%3d", L->data);
        L = L->next;
    }
    printf("\n");
}

//按位查找
//查找返回一個節(jié)點
LNode *GetElem(LinkList L, int SearchPos)
{
    if(SearchPos<1)
    {
        return NULL;
    }
    int j=1;//計數(shù),初始為1
    LNode *p=L->next;
    while(p!=NULL && j<SearchPos)
    {
        p=p->next;
        j++;
    }
    return p;
}

//按值查找
LNode *LocateElem(LinkList L, ElemType e)
{
    LNode *p = L->next;
    while(p!=NULL && p->data!=e)
        p = p->next;
    return p;
}

//向第i個位置插入元素
//使用GetElem找到第i-1個節(jié)點的位置(地址、指針)
bool ListFrontInsert(LinkList L, int InsertPos, ElemType InsertVal)
{
    LinkList p = GetElem(L, InsertPos-1);//GetElem函數(shù)中已自帶InsertPos-1是否合法的檢查
    if(NULL==p)
        return false;
    LinkList q;
    q = (LNode*) malloc(sizeof (LNode));
    q->data = InsertVal;
    q->next = p->next;
    p->next = q;
    return true;
}

//刪除第i個位置的元素
bool ListDelete(LinkList L, int i) 
{
    //判斷i的合法性已經在GetElem中定義過
    //若i=1也是合法的,此時i-1=0,返回頭指針
    LinkList p= GetElem(L, i-1);
    if(NULL==p)
    {
        return false;
    }
    LinkList q = p->next;
    //此時可能會說,不定義q,用p->next=p->next->next
    //這樣是不行的,因為被刪除的節(jié)點沒有了指針指向,無法free
    p->next = q->next;//斷鏈
    free(q);//釋放被刪除節(jié)點的空間
}

int main() {
    //輸入1 2 3 4 5 6 7 8 9 9999
    LinkList L;//L是鏈表頭,是結構體指針類型,大?。?個字節(jié)
//    list_head_insert(L);//頭插法新建鏈表
    list_tail_insert(L);
    print_list(L);
    //查找
    LinkList search;//查找指針
    //按位置查找
    search=GetElem(L, 2);//返回一個指針
    if(search!=NULL)
    {
        printf("Succeeded in searching by serial number\n");
        printf("%d\n", search->data);
    }else{
        printf("Failed in searching by serial number\n");
    }
    //按值
    search=LocateElem(L, 6);
    if(search!=NULL)
    {
        printf("Succeeded in searching by serial number\n");
        printf("%d\n", search->data);
    }else{
        printf("Failed in searching by serial number\n");
    }

    //在第2個位置上插入99
    bool ret;
    ret=ListFrontInsert(L, 2, 99);
    print_list(L);
    //刪除鏈表第4個位置的元素
    ListDelete(L, 4);
    print_list(L);
    return 0;
}

輸入:1 2 3 4 5 6 7 8 9999(用空格隔開)?

實驗結果:

帶頭結點的鏈表,數(shù)據(jù)結構,算法

?文章來源地址http://www.zghlxwxcb.cn/news/detail-742913.html

?

到了這里,關于【數(shù)據(jù)結構】——單鏈表的基本操作(帶頭結點)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 數(shù)據(jù)結構上機練習——單鏈表的基本操作、頭文件、類定義、main函數(shù)、多種鏈表算法的實現(xiàn),含注釋

    數(shù)據(jù)結構上機練習——單鏈表的基本操作、頭文件、類定義、main函數(shù)、多種鏈表算法的實現(xiàn),含注釋

    ??頭文件和源文件分開有很多好處:可以提高編譯速度、提高代碼的可維護性、提高代碼的可重用性和可擴展性,同時也可以使代碼結構更清晰,方便代碼的管理和維護。 LinkList.h test.cpp ????????????? ?? (下面所有函數(shù)都默認在類中實現(xiàn)) ??我們以

    2024年02月07日
    瀏覽(97)
  • 數(shù)據(jù)結構——單鏈表基本操作實現(xiàn) (c++)

    數(shù)據(jù)結構——單鏈表基本操作實現(xiàn) (c++)

    單鏈表鏈式存儲結構的特點是:用一組任意的存儲單元存儲線性表的數(shù)據(jù)元素(這里存儲單元可以是連續(xù)的,也可以是不連續(xù)的),為了表示每個數(shù)據(jù)元素a與其直接后繼數(shù)據(jù)元素之間的邏輯關系,除了存儲信息本身外還要存儲一個指示其直接后繼的信息(地址). 這兩部分信

    2024年02月03日
    瀏覽(88)
  • 數(shù)據(jù)結構——單鏈表上基本操作的實現(xiàn)

    1.按位序插入(帶頭結點) : ==ListInsert(L, i, e): ==在表L 中的第 i 個位置上插入指定元素 e = 找到第 i-1 個結點 ( 前驅結點 ) ,將新結點 插入其后;其中頭結點可以看作第 0 個結點,故 i=1 時也適用。 typedef struct LNode{ ElemType data; struct LNode *next; }LNode, *LinkList; // 在第 i 個位置插入

    2024年01月21日
    瀏覽(91)
  • 【數(shù)據(jù)結構】單鏈表基本操作:查找、插入、刪除、創(chuàng)建

    【數(shù)據(jù)結構】單鏈表基本操作:查找、插入、刪除、創(chuàng)建

    ?鏈表由結點組成,結點由數(shù)據(jù)域和指針域組成。其中,數(shù)據(jù)域存放的就是數(shù)據(jù)元素,指針域存放下一個結點的地址。數(shù)據(jù)元素可以只有一個,也可以有多個不同類型的數(shù)據(jù)元素,甚至是數(shù)組。下圖和代碼來自《C Primer Plus》,該鏈表每個節(jié)結點同時含char類型和int類型。 ??

    2024年02月02日
    瀏覽(97)
  • 數(shù)據(jù)結構---雙向鏈表的基本操作

    頭插法 遍歷鏈表 尾插法 頭刪法 尾刪法 按位置插入數(shù)據(jù) 按位置刪除數(shù)據(jù) dooublelinklist.c doublelinklist.h doublemain.c

    2024年02月22日
    瀏覽(96)
  • c語言數(shù)據(jù)結構——鏈表的實現(xiàn)及其基本操作

    c語言數(shù)據(jù)結構——鏈表的實現(xiàn)及其基本操作

    順序表的問題及思考 問題: 中間/頭部的插入刪除,時間復雜度為O(N) 增容需要申請新空間,拷貝數(shù)據(jù),釋放舊空間。會有不小的消耗。 增容一般是呈2倍的增長,勢必會有一定的空間浪費。例如當前容量為100,滿了以后增容到 200,我們再繼續(xù)插入了5個數(shù)據(jù),后面沒有數(shù)據(jù)插

    2023年04月09日
    瀏覽(97)
  • 【數(shù)據(jù)結構】C語言實現(xiàn)雙鏈表的基本操作

    【數(shù)據(jù)結構】C語言實現(xiàn)雙鏈表的基本操作

    大家好,很高興又和大家見面啦?。?! 經過前面幾個篇章的內容分享,相信大家對順序表和單鏈表的基本操作都已經熟練掌握了。今天咱們將繼續(xù)分享線性表的鏈式存儲的第二種形式——雙鏈表。在今天的內容中,咱們將介紹雙鏈表的創(chuàng)建以及一些基本操作,接下來跟我一起

    2024年02月04日
    瀏覽(97)
  • 數(shù)據(jù)結構 2.1 線性表的定義和基本操作

    數(shù)據(jù)結構 2.1 線性表的定義和基本操作

    數(shù)據(jù)結構三要素——邏輯結構、數(shù)據(jù)的運算、存儲結構(物理結構) 線性表是具有 相同數(shù)據(jù)類型 的n(n=0)個數(shù)據(jù)元素的 有限序列 ,其中n為表長,當n=0時,線性表是一個空表。 每個數(shù)據(jù)元素所占空間一樣大,有次序。 幾個概念 1.ai是線性表中的第i個 i表示元素線性表中的

    2024年02月07日
    瀏覽(90)
  • 【數(shù)據(jù)結構】 循環(huán)雙鏈表的基本操作 (C語言版)

    【數(shù)據(jù)結構】 循環(huán)雙鏈表的基本操作 (C語言版)

    目錄 一、循環(huán)雙鏈表 1、循環(huán)雙鏈表的定義: 2、循環(huán)雙鏈表的優(yōu)缺點: 二、循環(huán)雙鏈表的基本操作算法(C語言)? ??1、宏定義 ?2、創(chuàng)建結構體 3、循環(huán)雙鏈表的初始化? 4、循環(huán)雙鏈表按位查找 5、循環(huán)雙鏈表插入 6、循環(huán)雙鏈表查找 7、循環(huán)雙鏈表刪除 8、求循環(huán)雙鏈表長

    2024年01月22日
    瀏覽(99)
  • 數(shù)據(jù)結構實驗---順序表的合并---鏈表的基本操作---重點解析約瑟夫問題

    數(shù)據(jù)結構實驗---順序表的合并---鏈表的基本操作---重點解析約瑟夫問題

    實驗的寫法多種多樣,但本文并未采用 #define 定義容量的寫法,這樣寫已經是很老舊過時的寫法。所有實驗主體采用均為動態(tài)開辟,后續(xù)如果利用 C++ 來寫或許會應用更多語法… 本篇展示數(shù)據(jù)結構的兩個實驗 其中,重點分析約瑟夫問題 實驗中代碼的命名風格等均與下方博客

    2024年02月16日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包