zoukankan      html  css  js  c++  java
  • 数据结构-王道2017-第2章 线性表-2.3 线性表的链式表示

    1.线性表的链式存储又称为单链表,它是通过一组任意的存储单元来存储线性表中的数据元素,是非随机存取的存储结构,通常用“头指针”来标识一个单链表,如单链表L,头指针为“NULL”时则表示一个空表,此外,为了操作上的方便,在单链表第一个节点之前附加一个节点,称为头节点。头节点的数据域可以不设任何信息,也可以记录表长等相关信息。头指针的指针域指向线性表的第一个元素节点。

      头指针和头节点的区别:不管带不带头节点,头指针始终指向链表的第一个节点。而头节点是带头节点链表的第一个节点,结点内通常不存储信息。

     使用头节点的优点:

       1)开始结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作和在表的其他位置上的操作一致,无须进行特殊处理

       2)无论链表是否为空,其头指针是指向头节点的非空指针,空表中头节点的指针域为空,因此空表和非空表的处理也就统一了。

    typedef struct LNode{
        ElemType data;        //数据域
        struct LNode *next;    //指针域 
    }LNode, *LinkList;   

    2. 单链表上基本操作的实现

       

    //1.采用头插法建立单链表
    LinkList creatList(LinkList &L) {
        LNode *s; int x;
        L = (LinkList)malloc(sizeof(LNode));  //创建头结点
        L->next = NULL;     //初始为空链表
        scanf("%d", &x);   //输入结点的值
        while (x != 9999) {   //输入9999表示结束
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x;
            s->next = L->next;  //把头节点后面的链表加在新插入节点的后面
            L->next = s;        //修改头节点的指针到s
            scanf("%d", &x);
        }
        return L;
    }

    //打印链表
    void printLinkList(const LinkList &L){
        LNode * s = L;
        while (s->next != NULL) {
            printf("%d ", s->next->data);
            s = s->next;
        }
    }
    //2.采用尾插法建立单链表
    //必须增加一个尾部指针,使它始终指向当前链表的尾结点
    LinkList creatList2(LinkList &L) {
        
        L = (LinkList)malloc(sizeof(LNode));
        LNode *r = L, *s;   //r为指向尾部结点的指针
        int x;
        scanf("%d", &x);
        while (x != 9999) {
            s = (LNode*)malloc(sizeof(LNode));
            s->data = x;
            r->next = s;
            r = s;
            scanf("%d", &x);
        }
        r->next = NULL;    //如果不在这一步把指针置为NULL,那么指针的值是未知的而且不会是NULL,在遍历打印链表时(s->next != NULL)条件会满足,会继续访问未知内存的数据,从而使程序崩溃
        return L;
    
    }
    //3.按序号查找节点值
    LNode* getElem(LinkList L, int i) {
    
        if (i == 0)  return L;
        if (i < 0) return NULL;  //值无效
    
        int j = 1;             //第一个结点
        LNode* p = L->next;   //p为第一个结点指针
        while (p&&j < i) {
            p = p->next;
            j++;
        }
        return p;   //当j==i时返回结点,如果i > 总长度,则返回NULL
    }
    //4.按值查找结点值
    LNode* locateElem(const LinkList L, ElemType x) {
        LNode* p = L->next;
        while (p != NULL && p->data != x)
            p = p->next;
        return p;      //找到则返回指向该节点的指针,没有找到则返回NULL
     }
    //5.插入结点操作(在结点i后插)
    LNode* insertNode(LinkList& L, ElemType e,int i) {
    
        LNode* p = getElem(L, i);
        if (p == NULL)
            return NULL;
    
        LNode* s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return s;
    }
    //6.删除结点操作
    bool deleteElem(LinkList& L, int i) {
        LNode* p = getElem(L, i - 1);
        if (p == NULL)  return false;
    
        LNode* q = p->next;
        if (q != NULL) {       //q不是最后一个结点
            p->next = q->next;
            free(q);  //释放所占的内存空间
            return true;
        }        
        
        return false;   //节点不存在,删除失败
    }
    //如果是删除某一个节点*p,可以采用拷贝p的后继节点来给自身,然后删除p的后继节点来实现

     3.双链表

    typedef struct LNode {
        ElemType data;        //数据域
        struct LNode  *pre, *next;   //前驱和后继指针  
    }LNode, *LinkList;

    其余除了在插入和删除方面需要更新前驱结点外,跟单链表差别不大

  • 相关阅读:
    Go 交叉编译
    go module 基本使用
    win10中安装Linux子系统
    VsCode/Pycharm配合python env 使用
    python virtualenv 基本使用
    Django 知识点小记
    Django中一种常见的setting与账密保存/读取方式
    win安装python模块出现依赖问题的解决方法 & No module named 'MySqldb'
    MySQL数据库文件
    如何在MySQL中分配innodb_buffer_pool_size
  • 原文地址:https://www.cnblogs.com/--CYH--/p/6537944.html
Copyright © 2011-2022 走看看