博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线性表之单链表
阅读量:5965 次
发布时间:2019-06-19

本文共 3667 字,大约阅读时间需要 12 分钟。

单链表的形式:

  单链表的每节点中除了数据域外,还包含一个指针域,用来指向下一个节点,主要有带头结点和不带头结点两种。

  单链表定义如下:

//单链表结构体定义typedef struct LNode {    int data;    struct LNode* next;}LNode;

单链表中的两种基本算法:

插入操作:

  .不妨设在节点A和节点B直间插入节点S,则具体分两步实现:

  •   节点S指向节点B,
//让节点S指向BS->next = A->next;
  •   节点A指向S
//节点A指SA->next = S

  注意,这两步的顺序不能弄反,否则会丢失数据;

 

删除操作:

  同理,不妨设删除节点B,则只需要找到前一个节点A即可,具体实现如下:

//p是要删除的节点p = A->next;A->next = A->next->next;//释放节点B的空间free(p);

 

具体的相关算法实现:

头插法建立单链表:

  插入的新节点在表头,旧的节点在新节点之后,不妨设已有头节点B,现插入节点A,则形式为A->B,关键代码如下所示:

  

A->next = B->next;B->next=A;

  具体实现如下:

  

//插入的节点在表头STATUS CreateListOfF(LNode *&P, int a[], int n) {    //s用来指向新申请的节点    LNode* s;    int i;    //申请P的头结点    P =(LNode*) malloc(sizeof(LNode));    P->next = NULL;    for (i = 0; i < n; i++) {        s = (LNode*)malloc(sizeof(LNode));        s->data = a[i];        //新节点指向旧节点        s->next = P->next;        //新节点称为新的开始节点        P->next = s;    }    return OK;}

尾插法建立单链表如下所示:

  关键在于新插入的节点在链表的尾部,不妨设最后插入的节点是F,则最后必须加上F->next = NULL,具体实现如下:

  

//插入的节点在表尾STATUS CreateListOfR(LNode *&P, int a[], int n) {    //s指向新申请的节点,r直线链表的终端节点    LNode *s,*r;    int i;    //头结点的申请    P = (LNode*)malloc(sizeof(LNode));    P->next = NULL;    r = P;    for (i = 0; i < n; i++) {        s = (LNode*)malloc(sizeof(LNode));        s->data = a[i];                //r指向终端节点        r->next = s;        r = s;    }    r->next = NULL;    return OK;}

打印链表元素:

STATUS PrintList(LNode *P) {    if (P->next == NULL) {        return ERROR;    }    while (P->next != NULL) {        cout << P->next->data << "\t";        P = P->next;    }    cout << endl;    return OK;}

 查找某个元素并将其删除:

  删除元素两个关键点:

  • 待删除节点的查找;
  • 待删除节点的前驱节点;

  具体实现如下:

  

STATUS FindAndDel(LNode *&P,int x) {    //pre指向待删除节点的前一个节点    LNode *pre, *p;    p = P->next;    pre = P;    while (p != NULL) {        if (p->data == x) {            break;        }        pre = p;        p = p->next;    }        //查找部分结束    if (p == NULL) {        return ERROR;    }    else {        //让p前驱节点指向p后继节点        pre->next = p->next;        free(p);        return OK;    }}

将两个有序递增链表A、B合并成一个递增有序链表C:

  递增有序链表在这使用尾插法,将两个有序的链表的元素一一比较,将较小的一个插入C中,依次递推。

  注意: A和B中的元素有可能一个已经完全插入,另外一个部分插入。不妨设A完全插入,B部分插入,这说明B的剩下元素完全大于B,这是只需要将B接入C即可;

  具体实现如下:

 

STATUS MergeListRise(LNode *A, LNode *B, LNode *&C) {    LNode *pA = A->next;    LNode *pB = B->next;    C = A;   C->next = NULL;    //r始终指向C节点    LNode *r;    r = C;    free(B);        while (pA != NULL&&pB != NULL) {        if (pA->data <= pB->data) {            r->next = pA;            r = pA;        pA = pA->next;        }        else {            r->next = pB;            r = pB;        pB = pB->next;        }    }    r->next = NULL;    //处理有一部分插完而另外一部分未插完;    if (pA != NULL) {        r->next = pA;    }    if (pB->next != NULL) {        r->next = pB;    }    return OK;}

将两个有序递增链表A、B合并成一个递减有序链表C:

  同上述合并成一个递增有序链表类似,但这里使用头插法构建C,不需要r指针指向C的尾节点,具体实现如下:

  

STATUS MergeListFall(LNode *A, LNode *B, LNode *&C) {    LNode *pA = A->next;    LNode *pB = B->next;    C = A;    C->next = NULL;    free(B);    //s指向待插入的节点    LNode *s;    while (pA!=NULL&&pB!=NULL)    {        if (pA->data <= pB->data) {            //取得待插入节点s            s = pA;            pA = pA->next;            s->next = C->next;            C->next = s;        }        else        {            s = pB;            pB = pB->next;            s->next = C->next;            C->next = s;        }    }    //当某一个链表先处理完时    while (pA != NULL)    {        s = pA;        pA = pA->next;        s->next = C->next;        C->next = s;    }    while (pB != NULL)    {        s = pB;        pB = pB->next;        s->next = C->next;        C->next = s;    }    return OK;}

 

  

 

转载于:https://www.cnblogs.com/zuixime0515/p/9611522.html

你可能感兴趣的文章
MVC中的三个模块
查看>>
Line: 220 - com/opensymphony/xwork2/spring/SpringObjectFactory.java:220:-1
查看>>
oracle 常用命令大汇总
查看>>
2012年春运火车票电话和网上订票技巧、攻略
查看>>
根据request获取请求路径
查看>>
mysql 并行复制
查看>>
傲不可长,欲不可纵,乐不可极,志不可满——提高个人修养
查看>>
linux系统增加swap容量的方法
查看>>
后台调用gps
查看>>
HTML5标签的语义认知和理解(1)
查看>>
MySQL日志功能详解(2)
查看>>
HP LaserJet 305X 和 339X 系列一体机如何设置手动或自动接收传真?
查看>>
linux之权限之隐藏权限
查看>>
XDCTF成长记录
查看>>
Linux系统中的文本处理工具
查看>>
IDE---Python IDE之Eric5在window下的安装
查看>>
Mybatis调用Oracle中的存储过程和function
查看>>
telnet :No route to host
查看>>
基本安装lnmp环境
查看>>
yum源资料汇总
查看>>