創(chuàng)建鏈表:頭插法與尾插法

兩種方法的區(qū)別無非是插入的位置:
頭插法:新插入結(jié)點始終未當(dāng)前的第一個結(jié)點
尾插法:新插入結(jié)點始終為當(dāng)前的最后一個結(jié)點

頭插法建表

實現(xiàn)代碼:

//頭插法建鏈表 
void HeadCreateList(LinkList L,int n)
{   
    int i;
    srand(time(0));    //初始化隨機(jī)數(shù)種子
    L = (LinkList)malloc(sizeof(LNode));
    L ->next = NULL;

    LinkList p;
    //利用循環(huán)生成結(jié)點并添加到單鏈表中 
    for(i = 0;i < n;i++)
    {
        p = (LinkList)malloc(sizeof(LNode));    //生產(chǎn)新結(jié)點 
        p ->data = rand()%100 + 1;              //生產(chǎn)兩位隨機(jī)數(shù)100
        p ->next = L ->next;    
        L ->next = p;                      //插到表頭 
    }   
}

尾插法建表

實現(xiàn)代碼:

void TailCreateList(LinkList L,int n)
{
    LinkList p,tail;
    int i;
    srand(time(0));    //初始化隨機(jī)數(shù)種子
    L = (LinkList)malloc(sizeof(LNode));
    tail = L;
    for(i = 0;i < n;i++)
    {
        p = (LinkList)malloc(sizeof(LNode));    //生產(chǎn)新結(jié)點 
        p ->data = rand()%100 + 1;              //生產(chǎn)兩位隨機(jī)數(shù)100
        tail ->next = p;        //將表尾終端結(jié)點的指針指向新結(jié)點 
        tail = p;      //將當(dāng)前的新結(jié)點定義為表尾的尾結(jié)點 
    }
    tail->next = NULL;       //當(dāng)前鏈表結(jié)束 
} 


有趣的算法:查找單鏈表的中間結(jié)點

就是給你一個單鏈表,要你獲得單鏈表中位置中間的結(jié)點?你會怎么做?
一般我們可能用一個指針,從頭到尾擼一遍,同時記錄單鏈表的長度,然后再除以2得出第幾
項為中間結(jié)點,然后再擼length / 2獲得中間節(jié)點,重復(fù)遍歷很繁瑣,有沒有其他的方法呢?
有,肯定有,這里提供一個簡單的方法:
用兩個不同的指針,按照不同的移動順序來移動,這里我們暫且把他們成為快慢指針!
每次循環(huán),
快指針向后移動兩個結(jié)點: p = p -> next -> next;
慢指針向后移動一個結(jié)點: q = q -> next;

當(dāng)快指針到達(dá)尾部的時候,慢指針不就指向中間結(jié)點了,你說是吧~
原理非常簡單,下面我們寫下代碼實現(xiàn):

Status GetMidLNode(LinkList *L,ElemType *e)
{
    LinkList p,q;
    p = q = *L;
    while(p ->next ->next != NULL)
    {
        if(p ->next ->next != NULL)
        {
            p = p ->next ->next;
            q = q ->next;
        }else{
            p = p ->next;
        }
    } 
    e = q ->data;
    return OK;
} 

12種基礎(chǔ)基本操作代碼實現(xiàn)

從本節(jié)開始就不像上一節(jié)一樣一步步地講解了,直接上代碼,難點部分會寫下注釋!

1)構(gòu)造空表

void InitList(LinkList L)
{
    L = (LinkList)malloc(sizeof(LNode));
    if(!L)exit(ERROR);
    L ->next = NULL;
}

2)將鏈表置為空表

void ClearList(LinkList L)
{
    LinkList p = L ->next;
    L ->next = NULL;
    //接著就是釋放頭結(jié)點以外的結(jié)點了
    while(p)
    {
        p = L->next;
        free(L);  //釋放首元結(jié)點
        L = p;    //移動到當(dāng)前的首元結(jié)點 
    } 
} 

3)判斷是否為空表

這里要區(qū)分兩種情況:

有頭結(jié)點:L -> next = NULL;此時表為空表!
無頭結(jié)點:L = NULL;此時為空表!

Status ListEmpty(LinkList L)
{
    //有頭節(jié)點的情況,只需判斷頭結(jié)點的指針域是否為空即可
    if(L ->next)return FALSE;
    else return TRUE;   
}


4)銷毀單鏈表

void DestoryList(LinkList L)
{
    LinkList q;
    //刪除頭結(jié)點外的結(jié)點 
    while(L)
    {
        //指向首元結(jié)點,而不是頭結(jié)點     
        q = L ->next;
        free(L);
        L = q;      //刪除后指向首元 
    }
} 

5)獲得表長度

int ListLength(LinkList L)
{
    int i = 0;
    LinkList p = L ->next;
    while(p)
    {
        i++;
        p = p ->next;
    }
    return i;
} 

6)獲得表中第i個元素的值

Status GetElem(LinkList L,int i,ElemType *e)
{
    int j = 1;
    //指向首元,然后依次后移,假如到了結(jié)尾或者j的值大于i
    //還沒找個改元素說明i不合法
    LinkList p = L ->next;
    while(p && j < i)
    {
        j++;
        p = p ->next;
    } 
    if(!p || j> i)return ERROR;
    e = p ->data;
    return OK;
}

7)查找表中是否存在滿足條件的元素

int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{
    int i = 0;  
    LinkList p = L -> next;  
    while(p)  
    {  
        i++;  
        if(compare(p->data,e))return i;  
        p = p -> next;  
    }  
    return 0;  
} 

8)獲得某個結(jié)點的直接前驅(qū)

Status BeforeElem(LinkList L,ElemType choose,ElemType *before)
{
    LinkList q,p = L ->next;
    while(p ->next)
    {
        q = p ->next;
        //判斷p的后繼是否為choose,是的話返回OK,否則繼續(xù)后移 
        if(q ->data == choose)
        {
            before = p ->data;
            return OK; 
        }
        p = q;      
    }
    return ERROR; 
}

9.獲得某個結(jié)點的直接后繼

Status NextElem(LinkList L,ElemType choose,ElemType *behind)
{
    LinkList p = L ->next;
    while(p ->next)
    {
        if(p ->data == choose)
        {
            behind = p ->next ->data;
            return OK;
        }
        p = p ->next;
    }
    return ERROR;   
}

10.往表中第i個位置插入元素

Status ListInsert(LinkList L,int i,ElemType e)
{
    int j = 0;
    LinkList p,q =L;  //讓q指向頭結(jié)點
    while(p && j < i - 1)
    {
        j++;
        p = p ->next;  //p指向下一個節(jié)點 
    }
    if(!p || j > i - 1)return ERROR;
    p = (LinkList)malloc(sizeof(LNode));
    //要先讓插入的結(jié)點的指針域指向插入位置的后繼結(jié)點  
    //再讓插入節(jié)點的前驅(qū)的指針域指向插入結(jié)點  
    //?。?!順序不能亂哦1   
    p ->data = e;
    p ->next = q ->next;
    q ->next = p;
    return OK;
} 


11.刪除表中第i個元素

Status ListDelete(LinkList L,int i,ElemType *e)
{
    int j = 0;
    LinkList p,q = L;
    while(q ->next && j < i -1)
    {
        j++;
        q = q->next;
    }
    if(!q || j >i -1)return ERROR;
    p = q ->next;   //指向準(zhǔn)備刪除的結(jié)點
    q ->next = p ->next; //刪除結(jié)點的前驅(qū)的指針域指向刪除結(jié)點的后繼   
    e = p ->data; 
    free(p);    //釋放要刪除的結(jié)點  
    return OK;
}


12.遍歷單鏈表中的所有元素

void ListTraverser(LinkList L,void(*visit)(ElemType))
{
    LinkList p = L ->next;
    while(p)
    {
        visit(p ->data);
        p = p ->next;
    }
    printf("\n");
}

參考:https://www.it610.com/article/1277924529858953216.htm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容