取单链表中第 i 个元素值


知识点回顾:

单链表类型定义:

//类型定义
typedef struct Lnode{
    ElemType data;
    struct Lnode *next;
}Lnode, *LinkList

//变量定义
LinkList L;//注意此处是不加 * 的,原因看类型变量的结构体变量形式
Lnode *p,*s;//注意此处是加 * 的。原因如上

//重要操作
p=L;//p指向头结点
s=L->next;//s指向首元结点
p=p->next;//p指向下一结点

//单链表的基本操作:
//单链表的销毁
Status DestroyList_L(LinkList &L){
    //用于指向要销毁的结点
    Lnode *p;
    //循环条件,链表L非空(这是传入的参数)
    while(L){
        //让 指针p 用于指向要销毁的链表的头结点
        p = L;
        //让原本指向头结点的 指针L 指向下一个结点
        L = L->next;
        //释放 指针p 指向结点的内存。
        delete p;
    }
    return OK;
}

//清空单链表
Status ClearList(LinkList &L){
    Lnode *p, *q;
    //让指针p指向首元结点,即从首元结点开始清理,而非头结点!
    p = L->next;
    while(p){
        //指针q 指向 指针p 所指向结点的下一个结点
        q = p->next;
        delete p;
        p=q;
    }
    L->next = NULL;
    return OK;
}

//求单链表的表长
int ListLength_L(LinkList L){
    //定义一个 指针p 用以指向传入的单链表
    LinkList p;
    p=L->next;
    i=0;
    while(p){
        i++;
        p=p->next;
    }
    return i;
}

 

取值:取单链表中第 i 个元素的内容。

思考:顺序表里如何找到第i个元素?L->elem[i-1];

算法思路(分别取出表中第3个元素和第15个元素)

 

① 先找到首元结点,定义一个指针p,让其指向首元结点,即L->next,同时定义变量 j=1;

② 一直循环往下走,然后 j++,直到 j=3 时,获取 p->data ,也就是指针P所指向结点的数据域;

链表查找数据时,从链表的头指针出发,顺着链域next逐个结点往下搜索,直至搜索到第i个结点为止,

因此链表不是随机存取结构

③ 如果要找第15个元素,再继续的话,将指向空的,即没有元素,因此不需要继续向下寻找。

④ 注意 第几个元素 限制,初始值只能为 1 ,小于这个,肯定就是错的

算法步骤:

① 从第一个结点(L->next)顺链扫描,用 指针p 指向当前扫描到的结点,p初值 p=L->next;

② j 做计数器,累计当前扫描过的结点数,j 初值为1;

③ 当 指针p 指向扫描到的下一结点时,计数器 j 加1;

④ 当 j == i 时,指针p 所指的结点就是要找的第 i 个结点。

代码部分:

//获取线性表 L 中的某个数据元素的内容,通过变量 e 返回
//为什么要用&,这里要改变指针 变量e 本身的值,
//而非改变 e 所指内容的值!
//从链表 L 中获取第 i 个元素,元素的值由变量 e 返回。
Status GetElem_L(LinkList L, int i, ElemType &e){
    //初始化,给 指针p 赋值,跳过头结点,指向首元结点
    p = L->next;
    //初始化,定义一个计数器,初始值为1
    j = 1;
    //向后扫描,直到 指针p 指向第 i 个元素或 指针p 为空
    //当 j==i 时,即找到此元素,因此 j<i 不再成立,循环停止
    //当 i<1  时,即传入 i 不合法,因此无法找到,也不成立 
    //当 p为NULL 时,即找到最后都没找到,循环也停止
    while(p && j<i){
        p = p->next;
        //这里 j++ 和 ++j 都可以,对代码功能不会造成影响
        ++j;
    }
    //当指针为空,或者计数变量j大于i时,就证明运行出现了错误
    if(!p || j>i){
        return ERROR;
    }
    e = p->data;
    return OK;
}

 

个人感觉以上代码部分有点魔性,特此找到如下具有相同功能的代码:

LNode *GetElem(LinkList L, int i){
    //计数,初始值为1
    int j=1;
    //头指针L所指向结点的链域,也就是首元结点的地址赋值给 指针p
    LNode *p=L->next;
    //若i=0则返回头结点
    if(i==0){
        return L;
    //若 i 无效,则返回NULL
    }else if(i<1){
        return NULL;
    }
    //从首元结点开始找,查找到第 i 个结点。
    while(p&&j<i){
        p=p->next;
        j++;
    }
    //返回第 i 个结点的地址,若 i 大于表长则返回NULL
    return p;
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM