Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用

目录

1、循环链表

1.1 定义

1.2 优点

1.3 链表的终止条件

1.4 初始化链表

1.5 带有尾指针的循环链表

1.6 合并带有尾指针的两个循环链表

1.7 算法描述

2、双向链表

2.1 定义

2.2 双向链表的初始化

2.3 双向链表的插入

2.4 双链表的删除

3、单链表、循环链表、双向链表的时间效率比较

4、顺序表和链表的比较

5、线性表的合并

5.1 问题描述

5.2 代码呈现

6、有序表的合并

6.1 问题描述

6.2 算法步骤

6.3 代码呈现

7、链表的合并


1、循环链表

1.1 定义

是一种头尾相连的链表(即:表的最后一个结点的指针域指向 头结点,整个链表形成一个环)

1.2 优点

从表中的任何一个结点出发均可以找到表中的其他结点

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第1张图片

1.3 链表的终止条件

判断他们是否指向了头指针

p != L p -> next != L

1.4 初始化链表

//初始化一个循环单链表
bool InitList(LinkList &L){
    L=(LNode *)malloc(sizeof(LNode));//分配一个头结点
    if(L==NUll)         //内存分配不足,分配失败
        return false;
    L->next=L;          //头结点next指向头结点
    return true;
}

1.5 带有尾指针的循环链表

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第2张图片

1.6 合并带有尾指针的两个循环链表

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第3张图片

1.7 算法描述

LinkList Connect(LinkList Ta,LinkList Tb){
    p = Ta->next;               //p存表头结点
    Ts->next = Tb->next->next;   //Tb表头连接到Ta表尾
    delete Tb->next;            //释放Tb表头结点
    Tb ->next=p;                //修改指针
    return Tb;
}

2、双向链表

2.1 定义

在单链表中,查找直接后继结点的执行时间为O(1),而查找直接前驱的执行时间为O(n)。为克服单链表这种单向性的缺点,可利用双向链表(Double Linked List)。

顾名思义,在双向链表的结点中有两个指针域,一个指向直接后继,另一个指向直接前驱。结点结构如下图所示。

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第4张图片

双向循环链表

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第5张图片

2.2 双向链表的初始化

typedef struct DuLNode{
    ElemType data;          //数据域   
    struct DuLNode *prior;  //指向直接前驱
    struct DuLNode *next;   //指向直接后驱
}DuLNode,*DuLinkList;

2.3 双向链表的插入

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第6张图片

bool ListInsert_DuL(DuLinkList &L,int i,ElemType e){
    //在带头结点的双链表L中第i个位置之前插入元素e
    DuLNode *p,*s;
    if(!(p=GetElem_DuL(L,i)))       //在L中确定第i个元素的位置指针p
        return false;               //p为NULL时,第i个元素不存在
    s=(DuLNode *)malloc(sizeof(DuLNode));//生成新结点*s
    s->data=e;              //将结点*s数据域置为e
    s->prior=p->prior;      //将结点*s插入L中,此步对应上图①
    p->prior->next=s;       //对应上图②
    s->next=p;              //对应上图③ 
    p->prior=s;             //对应上图④
    return true;
}

2.4 双链表的删除

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第7张图片

void ListDelete_DuL(DuLinkList &L,int i){
    //删除带头结点的双向链表L中的第i个元素
    DuLNode *p,*s;
    if(!(p=GetElem_DuL(L,i)))       //在L中确定第i个元素的位置指针p
        return false;               //p为NULL时,第i个元素不存在
    p->prior->next=p->next;         //修改被删结点的前驱结点的后继指针,对应上图①
    p->next->prior=p->prior;        //修改被删结点的后继结点的前驱指针,对应上图②
    free(p);                        //释放被删结点的空间
}

3、单链表、循环链表、双向链表的时间效率比较

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第8张图片

4、顺序表和链表的比较

1)链式存储结构的优点:

  • 结点空间可以动态申请和释放

  • 数据元素的逻辑次序靠结点的指针来指示,插入和删除时不需要移动数据元素

2)链式存储结构的缺点:

  • 存储密度小,每个结点的指针域需要额外占用存储空间,当每个结点的数据域所占的字节不多时,指针域所占用存储空间的比重显得很大

  • 链式存储是非随机存取结构,对任一结点的操作都要从头结点依指针链查找到该结点,这增加了算法的复杂度

3)存储密度的大小

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第9张图片

一般地,存储密度越大,存储空间的利用率就越高。显然,顺序表的存储密度为1,而链表的存储密度小于1

4)顺序表和链表的比较

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第10张图片

5、线性表的合并

5.1 问题描述

假设利用两个线性表La和Lb分别表示两个集合A和B,现要求一个新的集合是二者的并集

5.2 代码呈现

void union(List &La,List Lb){
    La_len = ListLength(La);
    Lb_len = ListLength(Lb);
    for(i=1;i<=Lb_Len;i++){
        GetElem(Lb,i,e);
        if(!LocateELem(La,e))   ListInSert(&La,++La_Len,e)
    }
}

时间复杂度:O(ListLength(La)*ListLength(Lb),e);

6、有序表的合并

6.1 问题描述

已知线性表La和Lb中的数据元素按值非递减有序排列,现要求将La和Lb归并为一个新的线性表Lc,且Lc中的元素仍按值非递减有序排列

6.2 算法步骤

1)创建一个空表

2)依次从La或Lb中"摘取"元素值较小的结点插入到Lc表的最后,直至其中一个表变空为止

3)继续将La或Lb其中一个表的剩余结点插入到Lc表的最后

6.3 代码呈现

1)用顺序表实现

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第11张图片

void MergeList_Sq(SqList,SqList.SqList &LC){
    pa = LA.elem;
    pb = LB.elem;                       //指针pa和pb的初值分别指向两个表的第一个元素
    LC.length = LA.lenth+LB.length;       //新表长度为待合并两表的长度之和
    LC.elem = new ElemType[LC.length];    //为合并后的新表分配一个数组空间
    pc=LC.elem;                         //指针pc指向新表的第一个元素
    pa_last = LA.elem+LA.length-1;       //指针pa_last指向LA表的最后一个元素    
    pa_last = LB.elem+LB.length-1;       //指针pa_last指向LA表的最后一个元素
    while(pa<=pa_Last&&pb<=pb_last){     //两个表都非空
        if(*pa<=*pb)  *pc++=*pa++;       //依次"摘取"两表中值最小的结点
        else *pc++=*pb++;
    }
    while(pa<=pa_last)  *pc++=*pa++;    //LB已到达表尾,将LA中剩下的元素加入LC
    while(pa<=pa_last)  *pc++=*pb++;    //LA已到达表尾,将LB中剩下的元素加入LC
}//MergeList_Sq

空间复杂度:O(ListLength(La)+ListLEngth(Lb))

时间复杂度:O(ListLength(La)+ListLEngth(Lb))

7、链表的合并

Leap Day6——数据结构与算法 循环链表、双向链表、线性表的应用_第12张图片

你可能感兴趣的:(Leap,Plan,链表,数据结构,算法,c++)