数据结构--线性表的链式实现

1、线性链表的特点:

     线性表的链式存储结构是用一组任意的存储单元(可以是连续的物理存储空间也可以是不连续的)存储数据元素。

2、结点:数据元素的存储映像。由数据域(存储数据元素信息的域)和指针域(存储直接后继存储位置的域)组成。

     指针为数据元素之间的逻辑关系的映像。这种存储结构为非顺序映像或链式映像。

     n个结点组成链表,又称为单链表或线性链表。

3、整个链表的存储必须从头指针开始,头指针指示链表中的第一个结点的存储位置。

     由于最后一个数据元素没有直接后继,单链表中最后一个结点的指针为空(NULL)。

4、单链表可以由头指针唯一确定。

//线性表的链式存储结构
typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;

5、头结点

头结点位于单链表的第一个结点之前,数据域可以不存储任何数据,也可以存储线性表的长度之类的附加信息;指针域存储指向第一个结点的指针。

6、顺序表和单链表的区别

1)线性表的顺序存储结构中,任何两个元素的存储位置之间都可以从顺序表的起始位置计算得到,而在单链表中任何两个元素的存储位置之间没有固定的联系。

2)单链表是一种动态存储结构,整个可用存储空间可为多个链表共同享用,每个链表占用的空间可由系统应需求及时生成,不需要预先分配划定。

7、GetElem函数在单链表中的算法体现

//L为带头结点的单链表的头指针,当第i个元素存在时,其值赋给e并返回1,否则返回-1
int GetElem_L(LinkList L, int i, int &e){
    LNode* p = L->next; int j = 1;
    while (p&&j < i){
        p = p->next; ++j;
    }
    if (!p || j>i)return -1;
    e = p->data;
    return 1;
}

8、在单链表中实现插入和删除操作

在单链表元素a和b之间插入数据元素x,1)生成一个数据域为x的结点   2)修改a的指针域,令其指向x    3)x的指针域指向结点b  用语句描述即为s->next=p->next;p->next=s;

//在带头结点的第i个位置前插入元素e
int ListInsert_L(LinkList &L, int i, int e){
    LNode* p;
    p = L; int j = 0;
    while (p&&j < i - 1)
    { p = p->next; ++j; }//寻找第i-1个结点
    if (!p || j>i - 1)return -1;
    LNode *s = (LinkList)malloc(sizeof(LNode));//由系统生成一个LNode型的结点s
    s->data = e;
    s->next = p->next;
    p->next = s;
    return 1;

在线性链表a->b->c中,删除数据元素b,仅需要修改结点a中的指针域即可。语句描述为p->next=p->next->next;

//在带有头结点的线性链表L中删除第i个元素,并由e返回。
int ListDelete_L(LinkList &L, int i, int e){
    LNode *p = L; int j = 0;
    LNode *q;
    while (p->next&&j < i - 1){//让p指向第i个结点的前驱
        p = p->next; ++j;
    }
    if (!(p->next) || j>i - 1)return 0;
    q = p->next; p->next = q->next; e = q->data; free(q);//新结点q记录要删除的第i个结点元素最后再由系统回收LNode型结点

    return e;  
}

9、单链表的创建

由于用指针创建的单链表是一种动态存储结构(用数组描述的单链表为静态结构),因此单链表的建立过程就是一个动态生成链表的过程。从空表的状态开始,依次建立结点并插入链表。

1)尾插入法

//逆位序输入n个元素的值,建立带表头结点的单链线性表L
void createList_L(LinkList &L, int n){
    //创建一个带头结点的单链表
    LNode *p;
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    for (int i = n; i >= 1; i--){
        p = (LinkList)malloc(sizeof(LNode));//创建新结点
        scanf_s("%d",&p->data);//输入元素值
        p->next = L->next; L->next = p;//插入到表头
    }
}

2)头插入法

 

10、将两个有序的链表合并为一个链表

//La和Lb非递减排序,归并后的Lc也是非递减序列
void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc){
    LinkList pa, pb, pc;
    pa = La->next; pb = Lb->next; pc = Lc; pc = La;//用La的头结点作为Lc的头结点
    while (pa&&pb){
        if (pa->data <= pb->data){
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else{
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    pc->next = pa ? pa : pb;
    free(Lb);
}

11、线性表的静态单链表存储结构(用一维数组来描述线性链表

这种方法便于在不设“指针”类型的高级程序设计语言中使用链表结构。

要点:1)数组的一个分量表示一个结点;

           2)用游标(指示器cur)代替指针指示结点在数组中的相对位置;

           3)数组的第零分量可看成头结点,其指针域指示链表的第一个结点;

           4)需要预先分配一个较大的存储空间(初始空间大小固定与顺序表类似);

           5)在做线性表的插入和删除操作时不需要移动元素,仅需修改指针。

           6)在静态链表中实现数据元素的插入和删除操作,为了分辨数组已使用和未使用的分量,将所有未被使用过以及删除的分量用游标链成一个备用的链表,插入时可从备用链表上取得第一个结点作为待插入的新结点;反之在删除时将从链表中删除下来的结点链接到备用链表上。

//用一维数组描述单链表
#define MAXSIZE 1000
typedef struct{
    int data;
    int cur;
}component,SLinkList[MAXSIZE];

假设S为SLinkList型变量,则S[0].cur指示第一个结点在数组中的位置

若设i=S[0].cur则S[i].data存储线性表第一个数据元素,S[i].cur指示第二个结点的位置

一般情况下若i表示第k个结点,则s[i].cur指示的是第k+1个元素的位置

i=S[i].cur的操作实为指针后移(P=P->next)

12、循环链表

特点:表中最后一个结点的指针域指向头结点,整个链表链成一个环,从表中任意一个结点出发均可以找到表中其他任意结点。

13、双向链表

双向链表的结点中有两个指针域,一个指向直接前驱,一个指向直接后继。

在双向链表中插入一个元素的关键语句:

s=(DuLinkList)malloc(sizeof(LNode));

s->data=e;

s->prior=p->prior;

p->prior->next=s;

s->next=p;

p->prior=s;

在双向链表中删除一个元素:

e=p->data;

p->prior->next=p->next;

p->next->prior=p->prior;

free(p);

双向链表是链表中最常用的一种结构,要求重点掌握。

 

 

 

 

 

 

 

 

 


 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜鸡变形记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值