溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

c++線性表的基本運(yùn)算是什么

發(fā)布時(shí)間:2022-03-22 16:07:07 來源:億速云 閱讀:125 作者:iii 欄目:大數(shù)據(jù)

今天小編給大家分享一下c++線性表的基本運(yùn)算是什么的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

第1節(jié):線性表

1.1 概念

線性表是一種簡單的線性結(jié)構(gòu),特點(diǎn)是在非空的有限集合中,且第一個(gè)元素沒有直接前驅(qū)元素,最后一個(gè)元素沒有直接后繼元素,其他元素都有唯一的前驅(qū)和后繼元素。

線性表有順序存儲(chǔ)結(jié)構(gòu)和鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。

1.2 順序存儲(chǔ)結(jié)構(gòu)

是指將線性表中的各個(gè)元素依次存放在一組地址連續(xù)的存儲(chǔ)單元中,通常將這種方法存儲(chǔ)的線性表稱為順序表。

假設(shè),線性表的每個(gè)元素需占用m個(gè)存儲(chǔ)單元,并以所占的第一個(gè)單元的存儲(chǔ)地址作為數(shù)據(jù)元素的存儲(chǔ)位置。則線性表中第i+1個(gè)元素的存儲(chǔ)位置location(ai+1)和第i個(gè)元素的存儲(chǔ)位置location(ai)之間滿足關(guān)系location(ai+1)=location(ai) + m。線性表中第i個(gè)元素的存儲(chǔ)位置與第一個(gè)元素的a1的存儲(chǔ)位置滿足以下關(guān)系,location(ai) =location(a1)+(i-1)*m。其中,第一個(gè)元素的位置location(a1)稱為起始地址或基地址。

順序表邏輯上相鄰的元素在物理上也是相鄰的。每一個(gè)數(shù)據(jù)元素的存儲(chǔ)位置都和線性表的起始位置相差一個(gè)和數(shù)據(jù)元素在線性表中的位序成正比的常數(shù)。只要確定了第一個(gè)元素的起始位置,線性表中的任一個(gè)元素都可以隨機(jī)存取,因此,線性表的順序存儲(chǔ)結(jié)構(gòu)是一種隨機(jī)存取的存儲(chǔ)結(jié)構(gòu)。由于C語言的數(shù)組具有隨機(jī)存儲(chǔ)特別,因此采用數(shù)組來描述順序表。如下所示:

typedef struct{
    DataType list[ListSize];
    int length;
}SeqList;

其中,DateType表示數(shù)據(jù)元素類型,list用于存儲(chǔ)線性表中的數(shù)據(jù)元素,length用來表示線性表中數(shù)據(jù)元素的個(gè)數(shù),SeqList是結(jié)構(gòu)體類型名。定義一個(gè)順序表代碼:SeqList L; 指向順序表的指針:SeqList *L;

順序表的基本運(yùn)算如下:

(1)初始化線性表:

void InitList(SeqList *L){
    L ->length =0; // 把線性表的長度設(shè)為0
}

(2)線性表非空判斷:

int ListEmpty(SeqList L){
    if(L.length ==0)
        return 1;
    else
        return 0;
}

(3)按序號(hào)查找:

int GetElem(SeqList L, int i, DataType *e) {
//查找線性表中第i個(gè)元素,查找成功將該值返回給e,并返回1表示成功,反正返回-1表失敗。
    if(i<1||i>L.length)
        return -1;
 
    *e = L.list[i-1];
 
    return 1;
}

(4) 按內(nèi)容查找:

int LocateElem(SeqList L,DataType e){
//查找線性表中元素值為e的元素
    int i;
    for (i = 0 ; L.length ;i++)
        if(L.list[i] == e)
        return i+1;
 
    return 0;//找不到返回0
}

(5)插入操作:

//在順序表的第i個(gè)位置插入元素e,成功返回1,失敗返回-1,順序表滿了返回0
int InsertList(SeqList *L,int i ,DataType e){
 
    int j;
    if(i<1|| i> L->length+1){
        return -1;
    }
    else if(L->length >= ListSize){
        return 0;
    }else{
        for(j=L->length ; j >=i ;j--){
            L->list[j] = L ->list[j-1];
        }
        L->list[i-1] =e ;//插入元素到i個(gè)位置
        L->length =L->length+1;
        return 1;
    }
}

(6)刪除操作:

int DeleteList(SeqList *L,int i ,DataType *e){
 
    int j;
    if(L->length<=0){
        return 0;
    }
    else if(i<1||i>L-length){
        return -1;
    }else{
        *e = L ->list[i-1];
        for(j=i;j<=L->length-1;j++){
            L->list[j-1] =L->length[j];
        }
        L->length = L->length-1;
        return 1;
     }
}

小結(jié):順序表的優(yōu)缺點(diǎn)。

(1)優(yōu)點(diǎn):無須關(guān)心表中元素之間的關(guān)系,所以不用增加額外的存儲(chǔ)空間;可以快速地取表中任意位置的元素。

(2)缺點(diǎn):插入和刪除操作需要移動(dòng)大量元素。使用前需事先分配好內(nèi)存空間,當(dāng)線性表長度變化較大時(shí),難以確定存儲(chǔ)空間的容量。分配空間過大會(huì)造成存儲(chǔ)空間的巨大浪費(fèi),分配的空間過小,難以適應(yīng)問題的需求。

1.3 線性表的鏈?zhǔn)酱鎯?chǔ)

在解決實(shí)際問題時(shí),有時(shí)并不適合采用線性表的順序存儲(chǔ)結(jié)構(gòu),例如兩個(gè)一元多項(xiàng)式的相加、相乘,這就需要另一種存儲(chǔ)結(jié)構(gòu)——鏈?zhǔn)酱鎯?chǔ)。它是采用一組任意的連續(xù)或非連續(xù)存儲(chǔ)單元存儲(chǔ)線性表的元素。為了表示每個(gè)元素ai與其直接后繼ai+1的邏輯關(guān)系,鏈?zhǔn)酱鎯?chǔ)不僅需要存儲(chǔ)元素本身,還要存儲(chǔ)一個(gè)指向其直接后繼元素的地址。這種存儲(chǔ)結(jié)構(gòu)被稱之為結(jié)點(diǎn)(node)。存儲(chǔ)元素的叫數(shù)據(jù)域,存儲(chǔ)地址的叫指針域。結(jié)點(diǎn)元素的邏輯順序稱之為線性鏈表或單鏈表。

因?yàn)榈谝粋€(gè)結(jié)點(diǎn)沒有直接前驅(qū)結(jié)點(diǎn),因此需要一個(gè)頭指針指向它。為了方便操作放在第一個(gè)元素結(jié)點(diǎn)之前一個(gè)結(jié)點(diǎn)稱之為頭結(jié)點(diǎn),頭指針變成指向頭結(jié)點(diǎn),其數(shù)據(jù)域可以存放如線表長度等信息,而指針域則存放第一個(gè)元素結(jié)點(diǎn)的地址信息。若該鏈表為空,則頭結(jié)點(diǎn)指針域?yàn)榭铡?/p>

因?yàn)?,最后一個(gè)元素沒有直接后繼元素,所以將其指針域設(shè)置為“Null”空。

單鏈表的存儲(chǔ)結(jié)構(gòu)用C語言描述:

typedef struct Node{
    DataType data;
    struct Node *next;
}ListNode,*LinkList;

其中,ListNode是鏈表的結(jié)點(diǎn)類型,LinkList是指向鏈表結(jié)點(diǎn)的指針類型。定義為:LinkList L = ListNode *L。

單鏈表的基本運(yùn)算如下:

(1)初始化單鏈表:

void InitList(LinkList *head){
    if((*head=(LinkList)malloc(sizeof(ListNode)))==NULL){
        //為頭結(jié)點(diǎn)分配存儲(chǔ)空間
        exit(-1);
    }
    (*head)->next = NULL; //將單鏈表的頭結(jié)點(diǎn)指針域置為空
}

(2)單鏈表非空判斷:

int ListEmpty(LinkList head){
    if(head->next == NULL){  //單鏈表為空
        return 1;
    }
    else
    {
        return 0;
    }
}

(3)按序號(hào)查詢操作:

//按序號(hào)查找單鏈表中第i個(gè)結(jié)點(diǎn)
ListNode *Get(LinkList head,int i){
    ListNode *p;
    int j;
    if(ListEmpty(head)){ //如果鏈表為空
        return NULL;
    }
 
    if(i<1){
        return NULL;
    }
 
    j =0;
    p =head;
    while(p->next !=NULL && j<i){//保證p的下個(gè)結(jié)點(diǎn)不為空
        p = p->next;
        j++;
    }
    if(j==i)//找到第i個(gè)結(jié)點(diǎn)
        return p;
    else
        return NULL;
}

(4)按內(nèi)容查找操作:

//按內(nèi)容查找單鏈表中元素值為e的元素
ListNode *LocateElem(LinkList head,DataType e){
    ListNode *p;
    p = head->next; //指針p指向第一個(gè)結(jié)點(diǎn)
    while(p){
        if(p->data != e){
            p=p->next;//繼續(xù)下一個(gè)
        }else{
            break;
        }
    }
    return p;
}

(5)定位操作:

int LocatePos(LinkList head,DataType e){
    ListNode *p;//定義一個(gè)指向單鏈表的結(jié)點(diǎn)的指針p
    int i;
    if(ListEmpty(head))//非空判斷
        return 0;
    
    p =head->next;//指針p指向一個(gè)結(jié)點(diǎn)
    i =1;
    wihle(p){
        if(p->data==e)
            return i;
        else
        {
            p=p->next;//指向下一個(gè)結(jié)點(diǎn)
            i++;
        }
    }
    if(!p)//如果沒有找到與e相等的元素
         return 0;
}

(6)插入新數(shù)據(jù)元素e:

int InsertList(LinkList head,int i,DataType e){
    ListNode *pre,*p;//定義第i個(gè)元素的前驅(qū)結(jié)點(diǎn)指針pre,新生結(jié)點(diǎn)指針p
    int j;
    pre =head; //指針pre指向頭結(jié)點(diǎn)
    j =0;
    while(pre->next!=NULL && j<i-1){ //循環(huán)直到直到i元素前驅(qū)結(jié)點(diǎn)
        pre = pre->next;
        j++;
    }
    if(j!=i-1)//如果沒找到,插入位置出錯(cuò)
        return 0;
    
    //新生一個(gè)結(jié)點(diǎn)
    if((p=(ListNode*)malloc(sizeof(ListNode)))==NULL){
        exit(-1);
    }
    p->data =e; //將e賦值給結(jié)點(diǎn)的數(shù)據(jù)域
    
    p->next =pre->next;
    pre->next =p;
    return 1;
}

(7) 刪除第i個(gè)結(jié)點(diǎn):

int DeleteList(LinkList head,int i,DataType *e){
    ListNode *pre,*p;
    int j;
    pre = head;
    j = 0;
    while(pre->next!=NULL && pre->next->next != NULL && j<i-1){
        pre = pre->next;    
        j++;
    }
    if(j!=i-1){
        return 0;
    }
    //指針p指向單鏈表中的第i個(gè)結(jié)點(diǎn),并將該結(jié)點(diǎn)數(shù)據(jù)域值賦值給e
    p = pre->next;
    *e =p->data;
    //將前驅(qū)結(jié)點(diǎn)的指針域指向要?jiǎng)h除結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)
    pre->next =p->next;
    free(p);//釋放p指向的結(jié)點(diǎn)
    return 1;
}
1.4 單鏈表與順序表的對(duì)比

(1)存儲(chǔ)方式:順序表用一組連續(xù)的存儲(chǔ)單元依次存儲(chǔ)線性表的數(shù)據(jù)元素;而單鏈表用一組任意的存儲(chǔ)單元存放線性表的數(shù)據(jù)元素。

(2)時(shí)間性能:采用循序存儲(chǔ)結(jié)構(gòu)時(shí)查找的時(shí)間復(fù)雜度為O(1),插入和刪除需要移動(dòng)平均一半的數(shù)據(jù)元素,時(shí)間復(fù)雜度為O(n)。采用單鏈表存儲(chǔ)結(jié)構(gòu)的查找時(shí)間復(fù)雜度為O(n),插入和刪除不需要移動(dòng)元素,時(shí)間復(fù)雜度僅為O(1)。

(3)空間性能:采用順序存儲(chǔ)結(jié)構(gòu)時(shí)需要預(yù)先分配存儲(chǔ)空間,分配空間過大會(huì)造成浪費(fèi),過小會(huì)造成問題。采用單鏈表存儲(chǔ)結(jié)構(gòu)時(shí),可根據(jù)需要進(jìn)行臨時(shí)分配,不需要估計(jì)問題的規(guī)模大小,只要內(nèi)存夠就可以分配,還可以用于一些特殊情況,如一元多項(xiàng)的表示。

1.5 循環(huán)單鏈表

循環(huán)單鏈表(circular linkedlist)是首尾相連的一種單鏈表,即將最后一個(gè)結(jié)點(diǎn)的空指針改為指向頭結(jié)點(diǎn)或第一個(gè)結(jié)點(diǎn)的形成一個(gè)環(huán)型,最后一個(gè)結(jié)點(diǎn)稱為尾指針:rear。判斷單鏈表為空的條件是head->next==NULL,而判斷循環(huán)單鏈表為空的條件是head->next==head。訪問第一個(gè)結(jié)點(diǎn)即rear->next->next。

如果將兩個(gè)循環(huán)單鏈表(LA,LB)合成一個(gè)鏈表,只需將一個(gè)表的表尾和另一個(gè)表的表頭連接即可。具體步驟為:

1,將LA->next = LB->next->next; 第一個(gè)結(jié)點(diǎn)。

2,釋放LB的頭結(jié)點(diǎn),free(LB->next);

3, 將LB的表尾與LA的表頭相連,LB->next = LA->next。

LinkList Link(LinkList head1,LinkList head2){
    ListNode *p,*q;
    p = head1;//p指向1頭結(jié)點(diǎn)
    while(p->next !=head1){//循環(huán)使指針p指向鏈表的最后一個(gè)結(jié)點(diǎn)
        p = p->next;
    }
    q = head2;
    while(q->next != head2){//同上
 
        q = q->next;
    }
    p->next = head2->next;//將第一個(gè)鏈表的尾端連接第二個(gè)鏈表的第一個(gè)結(jié)點(diǎn)
    
    q->next = head1; // 將第二個(gè)鏈表的尾端連接到第一個(gè)連接的第一個(gè)結(jié)點(diǎn)
    
    return head1;
}

說明:也可以把循環(huán)單鏈表中的頭結(jié)點(diǎn)成為哨兵結(jié)點(diǎn)。

1.6 雙向鏈表

雙向鏈表(double linked list)就是鏈表中的每個(gè)結(jié)點(diǎn)有兩個(gè)指針域,一個(gè)指向直接前驅(qū)結(jié)點(diǎn),另一個(gè)指向直接后繼結(jié)點(diǎn)。雙向鏈表的每個(gè)結(jié)點(diǎn)有data域、prior域、next域,共三個(gè)域。其中,data域?yàn)閿?shù)據(jù)域,存放數(shù)據(jù)元素;prior域?yàn)榍膀?qū)結(jié)點(diǎn)指針域;next域?yàn)楹罄^結(jié)點(diǎn)指針域。雙向鏈表為了方便操作也可以增加一個(gè)頭結(jié)點(diǎn),同時(shí)也像單鏈表一樣也具有循環(huán)結(jié)構(gòu),稱為雙向循環(huán)鏈表。

判斷帶頭結(jié)點(diǎn)的雙向循環(huán)鏈表為空的條件是:head->prior ==head || head->next == head。C語言描述:p=p->prior->next = p->next->prior。

雙向鏈表的結(jié)點(diǎn)存儲(chǔ)結(jié)構(gòu)描述如下:

typedef struct Node{
    DataType data;
    struct Node *prior;
    struct Node *next;
}DListNode,*DLinkList;

(1)在第i個(gè)位置插入元素值為e的結(jié)點(diǎn):

分析:首先找到第i個(gè)結(jié)點(diǎn);再申請(qǐng)一個(gè)新結(jié)點(diǎn),由s指向該結(jié)點(diǎn),將e放入數(shù)據(jù)域。然后修改p和s指向的結(jié)點(diǎn)的指針域,修改s的prior域,使其指向p的直接前驅(qū)結(jié)點(diǎn);修改p的直接前驅(qū)結(jié)點(diǎn)的next域,使其指向s指向的結(jié)點(diǎn);修改s的next域,使其指向p指向的結(jié)點(diǎn);修改p的prior域,使其指向s指向的結(jié)點(diǎn)。

int InsertDList(DListLink head,int i,DataType e){
    DListNode *p,*s;
    int j;
    p = head->next;
    j =0 ;
    while(p!=head&&j<i){
        p = p->next;
        j++;
    }
    if(j!=i){
        return 0;
    }
    s = (DListNode*)malloc(sizeof(DListNode));//給s創(chuàng)建新結(jié)點(diǎn)
    if(!s){
        return -1;
    }
    s->data=e; //e 賦值給s
    s->prior = p->prior; //把p的前驅(qū)指針賦值給s的前驅(qū)
    p->prior->next = s;//把s即e,賦值給p的前驅(qū)的后繼指針
    s->next =p;//把s的后繼為p
    p->prior =s;//p的前驅(qū)為s
    return 1;
}

c++線性表的基本運(yùn)算是什么

(2)刪除第i個(gè)結(jié)點(diǎn)

int DeleteDList(DListLink head,int i ,DataType e ){
 
    DListNode *p;
    int j;
    p = head->next;
    j= 0;
    while(p!=head&&j<i){
        p =p->next;   
        j++;
    }
    if(j!=i)
        return 0;
    
    p->prior->next =p->next;
    
    p->next->prior = p->prior;
    
    free(p);
    return 1;
}
1.7 靜態(tài)鏈表

上面各種鏈表結(jié)點(diǎn)的分配與釋放都是由函數(shù)malloc、free動(dòng)態(tài)實(shí)現(xiàn),因此稱為動(dòng)態(tài)鏈表。但是有的高級(jí)程序沒有指針類型,就不能利用上述辦法動(dòng)態(tài)創(chuàng)建鏈表,需要利用靜態(tài)鏈表實(shí)現(xiàn)動(dòng)態(tài)鏈表的功能。

利用一維數(shù)組實(shí)現(xiàn)靜態(tài)鏈表,類型說明如下:

typedef struct
{
    DataType data;
    int cur;
}SListNode;
 
typedef struct
{
    SListNode list[ListSize];//節(jié)點(diǎn)類型
    int av;      //備用鏈表指針
}SLinkList; //靜態(tài)鏈表類型

靜態(tài)循環(huán)鏈表:數(shù)組的一個(gè)分量表示一個(gè)結(jié)點(diǎn),同時(shí)用游標(biāo)(指示器cur)代替指針指示結(jié)點(diǎn)在數(shù)組中的相對(duì)位置。頭結(jié)點(diǎn)是數(shù)組的第0分量,其指針域指示鏈表的第一個(gè)結(jié)點(diǎn)。表中的最后一個(gè)結(jié)點(diǎn)的指針域?yàn)?,指向頭結(jié)點(diǎn)。例:線性表如下:

c++線性表的基本運(yùn)算是什么  

設(shè)s為SlinkList類型的變量,則s[0].cur指示頭結(jié)點(diǎn),如果令i=s[0].cur,則s[i].data表示表中的第1個(gè)元素“Yang”是 s[i].cur指示第2個(gè)元素在數(shù)組的位置。

靜態(tài)鏈表基本元素:

(1)初始化靜態(tài)鏈表:

void InitSList(SLink *L){
    int i;
    for(i=0;i<ListSize;i++){
        (*L).list[i].cur =i+1;
        (*L).list[ListSize-1].cur=0;
        (*L).av=1;
}

(2)分配結(jié)點(diǎn):

int AssignNode(SLinkList L){
    int i;
    i=L.av;
    L.av=L.list[i].cur;
    return i;
}

(3)回收結(jié)點(diǎn):

void FreeNode(SLinkList ,int pos){
    L.list[pos].cur = L.av;
    L.av=pos;
}

(4)插入操作:

void InsertSLink(SLinkList *L,int i,DataType e){
    int j,k,x;
    k=(*L).av;//從備用鏈中取出空閑結(jié)點(diǎn)
 
    (*L).av=(*L).list.cur;//使備用鏈表指向下一個(gè)有用結(jié)點(diǎn)
 
    (*L).list[k].data = e ;//將新元素放入空閑結(jié)點(diǎn)中
 
    //將新結(jié)點(diǎn)插入到對(duì)應(yīng)的位置上
    j =(*L).list[0].cur;
    for(x=1;x<i<i;x++){
        j=(*L).list[j].cur;
    }
    (*L).list[k].cur=(*L).list[j].cur;
    (*L).list[j].cur=k;
}

(5)刪除操作:

void DeleteSList(SLinkList *L,int i,DataType *e){
    int j,k,x;
    if(i == 1){
        k=(*L).list[0].cur;
        (*L).list[0].cur = (*L).list[k].cur;
    }
    else
    {
        j=(*L).list[0].cur;
        for(x=1);x<i-1;x++){
            j=(*L).list[j].cur;
        }
        k=(*L).list[j].cur;
        (*L).list[j].cur = (*L).list[k].cur;
    }
    (*L).list[k].cur = (*L).av;
    *e = (*L).list[k].data;
    (*L).av = k ;
}

以上就是“c++線性表的基本運(yùn)算是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI