线性表之链表

线性表-链表(索引)

  • 单、循环链表
    • 定义
    • 初始化
      • 不带头节点
      • 带头节点
  • 插入
    • 建立单链表(头插入法)
    • 建立单链表(尾插法)
    • 按位序插入
    • 指定节点(后插操作)
    • 指定节点(前插操作)
  • 查找
    • 查找节点的值(按序号)
    • 查找节点的值(按值)
  • 删除
    • 删除节点(按位序)
    • 删除指定节点*p
  • 汇总
1.1定义

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zdovwIx6-1601101792063)(…/BlogImages/带头VS不带头.png)]

                typedef unsigned int ElemType;
                typedef struct LNode {//定义单链表节点类型
                    ElemType data;// 数据域(每个节点存放一个数据元素)
                    struct  LNode* next;//指针域(指向下一个节点)
                }LNode, * LinkList;            
2.1初始化(不带头节点)
                //初始化一个空的单链表
                bool InitLinkList(LinkList& L) {
                    L = NULL;
                    return true;
                }  
2.2初始化(带头节点)
                //初始化一个带头节点单链表
                bool InitList(LinkList& L) {
                    L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
                    if (L == NULL)
                        return false;
                    L->next = NULL;
                    return true;
                }
3.1建立单链表(尾插法)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cVTjVgfY-1601101792068)(…/BlogImages/尾插法.png)]


                //尾插法通过尾指针r实现插入
                LinkList List_TailInsert(LinkList& L) {
                    int x;
                    L = (LinkList)malloc(sizeof(LNode));//①初始化单链表并将L指针指向头节点
                    LNode* s, * r = L;//②将s和r指针都指向头节点
                    scanf("%d", &x);//③输入值
                    while (x!=99)
                    {
                        s = (LinkList)malloc(sizeof(LNode));//④将s指针指向新的节点
                        s->data = x;//⑤给新节点赋输入的值
                        r->next = s;//⑥上一节点的next指向新的节点(上一节点通过r指针能找到)
                        r = s;//⑦将r指针指向新的表尾节点(通过s即可找到新的指针的表尾节点)
                        scanf("%d", &x);
                    }
                    r->next = NULL;//⑧尾节点指针置空
                    return L;
                }         
3.2建立单链表(头插入法)
                //头插法建立单链表
                LinkList List_HeadInsert(LinkList &L) {
                    LNode* s; int x;
                    L = (LinkList)malloc(sizeof(LNode));//初始化单链表并将L指针,指向头节点
                    L->next = NULL;//初始为空链表
                    scanf("%d", &x);//输入节点值
                    while (x!=99)
                    {
                        s = (LNode*)malloc(sizeof(LNode));//将s指针指向新的节点
                        s->data = x; //为新的节点赋输入的值
                        s->next = L->next;//将上一节next指针赋值给新节点的next指针
                        L->next = s;//将上一节点的next指针指向s
                        scanf("%d", &x);
                    }
                    return L;
                }   
3.3按位序插入(不带头节点)
                /// <summary>
                /// 补充不带头节点的按照位序插入
                /// </summary>
                /// <param name="L"></param>
                /// <param name="i"></param>
                /// <param name="e"></param>
                /// <returns></returns>
                bool ListInserWithoutHead(LinkList &L,int i,ElemType e) {
                    if (i < 1)
                        return false;
                    if (i == 1) {//由于不带头节点插入第一个系欸但那需要特殊处理
                        LNode* s = (LNode*)malloc(sizeof(LNode));
                        s->data = e;
                        s->next = L;
                        L = s;
                        return true;
                    }
                    LNode* p = L;
                    int j = 1; //p 指向第L个节点
                    while (p!=NULL &&j<i-1)
                    {
                        p = p->next;
                        j++;
                    }//找前驱节点
                    if (p == NULL)
                        return false;
                    LNode* s = (LNode*)malloc(sizeof(LNode));
                    s->data = e;
                    s->next = p->next;
                    p->next = s;
                    return true;
                }
3.4指定节点(后插操作)
                bool InsertNextNode(LNode* p, ElemType e) {
                    if (p == NULL)
                        return false;
                    LNode* s = (LNode*)malloc(sizeof(LNode));
                    s->data = e;
                    s->next = p->next;
                    p->next = s;
                    return true;
                }
3.5 指定节点(前插操作)
                /// <summary>
                /// 在指定节点前插操作(就是将指针域的值进行交换)
                /// </summary>
                /// <param name="p">节点</param>
                /// <param name="e">待插入元素</param>
                /// <returns></returns>
                bool InsertBeforeNode(LNode *p,ElemType e) {
                    if (p == NULL)
                        return false;
                    LNode* s=(LNode*)malloc(sizeof(LNode));
                    if (s == NULL)
                        return false;//内存分配失败
                    s->next = p->next;
                    p->next = s;
                    s->data = p->data;//赋值交换下
                    p->data = e;
                }
4.1查找节点的值(按序号),时间复杂度(O(n))
                LNode* GetElem(LinkList L,int i) {
                    int j = 1;//计数,初始化为1
                    LNode* p = L->next;//头节点赋值给指针p
                    if (i == 0)
                        return L; //若i=0 返回头节点
                    if (i < 1)
                        return NULL; //若i无效 返回null
                    while (p&&j<i)
                    {
                        p = p->next;
                        j++;
                    }
                    return p;
                }
4.2查找节点的值(按值),时间复杂度O(n)
      LNode* LocateElem(LinkList L, ElemType e) {
                    LNode* p = L->next;
                    while (p!=NULL &&p->data!=e)
                    {
                        p = p->next;
                    }
                    return p;
                }    
5.1 删除节点(按位序)
                /// <summary>
                /// 按位序删除节点
                /// </summary>
                /// <param name="L"></param>
                /// <param name="i"></param>
                /// <returns></returns>
                bool DelNode(LinkList &L,int i) {
                    if (i<1)
                        return false;
                    //按位序查找前驱节点
                    LNode* p;
                    int j = 0;//指向的是第几个节点 头节点为0
                    p = L;
                    while (p!=NULL&&j<i-1)
                    {
                        p = p->next;
                        j++;
                    }
                    //或者LNode* p = GetElem(L, i - 1);
                    if (p == NULL||p->next==NULL) //i值不合法或p后面没有节点了
                        return false;
                    LNode* q = p->next;//要删除的节点
                    p->next = q->next; //p指向删除的下一节点
                    free(q);
                    return true;
                }
5.2删除指定节点*p
                /// <summary>
                /// 删除*p
                /// </summary>
                /// <param name="p"></param>
                /// <returns></returns>
                bool DelBeforeNode(LNode *p) {
                    if (p == NULL)
                        return false;
                    LNode* q = p->next;
                    p->data = q->next->data;//把*p的后继节点*q的值赋值到前驱节点*p ,再移除q 与前插操作思想一致
                    p->next = q->next;
                    free(q);
                    return true;
                }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值