知识点回顾:
单链表类型定义:
//类型定义 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; }