线性表的链式表示和实现解析

合集下载

线性表的类型定义、顺序表示和实现

线性表的类型定义、顺序表示和实现
– ①ai-1 和 ai逻辑关系发生变化 – ②需移动元素:
i=n 只删 an即可 1≤i≤n -1 将ai+1 ~an前移
23
bool deleteElem(SqList& L,int pos)
typedef int ElemType;
typedef char ElemType;
等;
②同一线性表中的数据元素必须具有相同的特性,属同一类 型;
③a2,关…系, ra是i-1,一a个i, a有i+1序, …偶,对an的)集,合a,i-1即领对先于于非ai,空表的示线了性数表据(元a1,素 之间的相邻关系,称ai-1是ai的直接前驱,ai是ai-1的直接后继 ;
6
2.1.3 操作举例
例:假设利用两个线性表La和Lb分别表示两 个集合A和B,求一个新的集合A=A∪B。
算法:
– ①取得Lb中的1个元素; – ②在La中查找这个元素; – ③若不存在:插入La中;若存在,取Lb中下一个
元素,重复 ①、②、③,直到取完Lb的每个元素 。
7
void unionList(SqList &la,SqList lb)
10
线性表的顺序存储结构示意图
存储地址
loc(a1) loc(a1)+ k
内存空间状态 逻辑地址
a1
1
a2
2



loc(a1)+ (i- 1)k
ai
i



loc(a1)+ (n- 1)k
an
n 空闲
顺序存储结构可以借助于高级程序设计语言中的一维数组来表示。
11
用C++语言描述的顺序表类型如下所示: sqlist.h

数据结构线性表的链式表示和实现的实习报告

数据结构线性表的链式表示和实现的实习报告

数学与计算科学学院实验报告实验项目名称线性表的链式表示与实现所属课程名称数据结构实验类型验证型实验日期班级学号姓名成绩2.调试第一次显示错误如下:原因:由于没有头文件及宏定义以及自定义,因此导致许多错误,可能还有许多错误没有显示3. 将以下语句编入VC++6.0中#include "stdio.h"#include "stdlib.h"#define OK 1#define ERROR 0typedef int ElemType;typedef int Status;4.调试第二次显示错误如下:原因:由于算法中许多变量没有定义,因此有许多错误5. 将以下语句加入算法中:int i;LinkList p;(加入创建链表的算法中)LinkList p;int j;(加入查找元素的算法中)LinkList p,s;int j;(加入插入元素的算法中)LinkList p,q;int j;(加入删除元素的算法中)6.调试第三次显示没有错误:7. 现在开始编写主函数:(1)先编写调用创建链表的函数的主函数:如下:void main(){LinkList L;int i,n;scanf("%d",&n);CreateList_L(L,n);for(i=n;i>0;--i)printf("%d ",L->data);printf("\n");}调试显示为:运行显示为:产生了随机数说明for循环语句那里编写错误因此修改为:LinkList p;for(p=L->next;p!=NULL;p=p->next)printf("%d ",p->data);调试显示为:运行显示为:这次正确了那么继续编写下面的其他主函数,形成的总的主函数为:void main(){LinkList L,p;int i,n;scanf("%d",&n);CreateList_L(L,n);for(p=L->next;p!=NULL;p=p->next)printf("%d ",p->data);printf("\n");ElemType e;scanf("%d", &i);GetElem_L(L, i, e);printf("%d\n",e);scanf("%d",&i);scanf("%d",&e);ListInsert_L(L, i, e);for(p=L->next;p!=NULL;p=p->next)printf("%d ",p->data);printf("\n");scanf("%d", &i);ListDelete_L(L,i,e);printf("%d\n",e);for(p=L->next;p!=NULL;p=p->next)printf("%d ",p->data);printf("\n");}8.调试第四次显示为:9.运行显示结果为:10. 但运行后的界面显得很单调;要是忘记下一个算法是什么就容易输入出错,也不适合大众使用;因此为了将程序优化,所以在主函数中增加以下输入输出语句和条件语句;为了让程序更加严谨,因此还加入一些循环语句以及条件语句,那么主函数语句变为:main(){LinkList L,p;int i,n,x,y,z;ElemType e;printf("请输入您想构建的链式表的元素个数:\n");scanf("%d",&n);printf("请输入您想构建的链式表:\n");CreateList_L(L,n);printf("您构建的链式表是:\n");for(p=L->next;p!=NULL;p=p->next)printf("%d ",p->data);printf("\n");printf("请输入您想查找的元素是第几个元素:\n");scanf("%d", &i);for(x=2;(i<=0||i>n)&&x>=0;--x){switch(x){case 2:printf("输入的数字错误,还有两次重新输入符合要求的数字的机会:\n");break;case 1:printf("输入的数字错误,还有一次重新输入符合要求的数字的机会:\n");break;case 0:printf("输入的数字错误,您的输入机会已经用完\n");return ERROR;printf("%d ",p->data);printf("\n");return 0;}11.调试第五次显示为:、12.运行后结果显示为:这样那么程序就完整了,清晰明了,用户运行的时候也易知道自己要输入什么了【实验结论】(结果)。

第3章线性表的链式存储

第3章线性表的链式存储
L
(a) 空循环链表
L
a1
a2
...
an
(b) 非空循环链表
3.1.3 双向链表
在单链表结点中只有一个指向其后继结点的next 指针域,而找其前驱则只能从该链表的头指针开始,顺 着各结点的next指针域进行查找,也就是说找后继的时 间复杂度是O(1),找前驱的时间复杂度是O(n)。如果也 希望找前驱像后继那样快,则只能付出空间的代价:每 个结点再加一个指向前驱的指针域prior,结点的结构修 改为下图,这样链表中有两个方向不同的链,用这种结 点组成的链表称为双向链表。
1.带头结点的单链表 2.不带头结点的单链表
3.3.3 单链表插入操作的实现
单链表的插入操作是指在表的第i个位置结点处插入 一个值为data的新结点。插入操作需要从单链表的第一个结 点开始遍历,直到找到第i个位置的结点。插入操作分为在 结点之前插入的前插操作和在结点之后插入的后插操作。
1.前插操作 2.后插操作
2.整数型单链表算法
3.不带头结点的单链表算法
3.2.2 尾插法单链表的创建实现
用头插法实现单链表的创建,比较简单,但读入的 数据元素的顺序与生成的链表中元素的顺序是相反的。若希 望两者次序一致,则用尾插法创建单链表。为了快速找到新 结点插入到链表的尾部位置,所以需加入一个尾指针r用来 始终指向链表中的尾结点。初始状态:头指针L和尾指针r均 为空,把各数据元素按顺序依次读入,申请结点,将新结点 插入到r所指结点的后面,然后r指向新结点,直到读入结束 标志为止。
3.2.2 尾插法单链表的创建实现
L
插入P前的尾指针 插入P后的尾指针
r
3
4
P1
x^
2
3.3 单链表运算的实现

线性表的链式表示和实现(简单的插入和删除功能)

线性表的链式表示和实现(简单的插入和删除功能)

#include<iostream>using namespace std;#define ERROR 0#define OK 1class LNode{private:int num;LNode *next;public:friend LNode* LNodeCreate(); //创建链式线性表friend int GetElem(LNode *H,int i); //L为带头结点的单链表的头指针,当第i个元素存在,输出其值friend int LNodeInsert(LNode *H,int i,int e); //L为带头结点的单链表的头指针,在dii个位置插入元素efriend int LNodedelete(LNode *H,int i); //删除线性表中第i个元素};/*//从头到尾创建线性表LNode* LNodeCreate(){LNode *q,*H,*p;int size;cout<<"请输入线性表元素的个数:";cin>>size;cout<<"请输入线性表这"<<size<<"个元素:";q=H=new LNode;for(int i=0;i<size;i++){p=new LNode;cin>>p->num;H->next=p;H=p;}H->next=NULL;H=q->next;cout<<"刚创建的线性表为:";for(p=H;p!=NULL;p=p->next)cout<<p->num<<" ";cout<<endl<<endl;return H;}*///从尾到头创建线性表LNode* LNodeCreate(){LNode *L=new LNode,*p;L->next=NULL;int size,e;cout<<"请输入线性表元素的个数:";cin>>size;cout<<"请输入线性表这"<<size<<"个元素:";for(int i=size;i>0;--i){p=new LNode;cin>>e;p->num=e;p->next=L->next;L->next=p;}L=p;cout<<"刚创建的线性表为:";for(p=L;p!=NULL;p=p->next)cout<<p->num<<" ";cout<<endl<<endl;return L;}int GetElem(LNode *H,int i){LNode *p; int j=1; //j为计数器p=H;while(p&&j<i){p=p->next;++j;}if(!p&&j>i) return ERROR;cout<<"取出的值为:"<<p->num<<endl<<endl;return OK;}int LNodeInsert(LNode *H,int i,int e){LNode *p,*s; int j=1;p=H;while(p&&j<i-1){p=p->next;++j;}s=new LNode;s->num=e;s->next=p->next;p->next=s;cout<<"新的线性表为:";for(p=H;p!=NULL;p=p->next)cout<<p->num<<" ";cout<<endl<<endl;return OK;}int LNodedelete(LNode *H,int i){ LNode *p=H,*q;int j=1;while(p&&j<i-1){p=p->next;++j;}if(!p&&j>i) return ERROR;q=p->next;p->next=q->next;delete(q);cout<<"新的线性表为:";for(p=H;p!=NULL;p=p->next)cout<<p->num<<" ";cout<<endl<<endl;return OK;}int main(){LNode *H;int m;H=LNodeCreate();cout<<"请输入你要取出的元素的位置:"; cin>>m;GetElem(H,m);int i,e;cout<<"请输入你要插入的元素的位置:"; cin>>i;cout<<"请输入你要插入的元素:"; cin>>e;LNodeInsert(H,m,e);int j;cout<<"请输入你要删除的元素的位置:"; cin>>j;LNodedelete(H,j);return 0;}。

线性表的链式表示和实现(插入删除建空合并)

线性表的链式表示和实现(插入删除建空合并)

线性表的链式表⽰和实现(插⼊删除建空合并)题解:后续的功能会不定期更新emmm框架:代码:#include <iostream>#include <cstdio>using namespace std;typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;int GetElem_L(LinkList L, int i, int &e){LNode *p = L->next;int j = 1;while (p&&j < i){p = p->next;++j;}if (!p || j>i)return0;e = p->data;return1;}int ListInsert_L(LinkList &L, int i, int e){LNode *p = L->next;int j = 1;while (p && j < i-1){p = p->next;++j;}if (!p || j>i-1)return0;LNode *node =(LNode*)malloc(sizeof(LNode));node->data = e;LNode* q = p->next;p->next = node;node->next = q;return1;}int ListDelete_L(LinkList &L, int i, int &e){LNode *p = L->next;int j = 1;while (p->next&&j < i - 1)//注意此处为p->next,因为若是p,则出来的p可能为空 {p = p->next;++j;}if (!p->next || j>i - 1)return0;LNode*q= p->next;e = q->data;p->next = p->next->next;free(q);return1;}void CreateList_L(LinkList &L, int n){printf("Enter the value of the node:");// L = (LinkList)malloc(n*sizeof(LNode)); 如果像这样创建的话,//那就是⽣成连续存储空间的线性表,应该单独对每⼀个节点分配内存空间L = (LinkList)malloc(sizeof(LNode));L->next = nullptr;//先⽣成⼀个表头的单链表for (int i = n;i > 0;--i){LNode *p = (LinkList)malloc(sizeof(LNode));cin>>p->data;p->next = L->next;//插⼊⽅式为向表头的后⼀个插⼊,不然插在表尾太⿇烦 L->next = p;}}void MergeList_L(LinkList &L,LinkList &Lb,LinkList &Lc)//合并{LNode *p=L->next;LNode *pb=Lb->next;LNode *pc=Lc=L;while(p&&pb){if(p->data<=pb->data){pc->next=p;pc=p;p=p->next;}else{pc->next=pb;pc=pb;pb=pb->next;}}pc->next=p?p:pb;free(Lb);}/*int Length_L(LinkList &L)//计算长度{int j=0;LNode *p=L->next;while(p){p=p->next;j++;}return j;}*/ //没⽤到emmmmvoid ShowList(LinkList &L){LNode *p = L->next;while (p){cout<<p->data<<"";p = p->next;}}int main(){LinkList L;cout<<"Enter the length of the linked list:";int num;cin>>num;CreateList_L(L, num);//建表ShowList(L);//展⽰int e1,temp;cout<<"\nTo increase the number of positions:";int place;cin>>place;cout<<"\nEnter the number to insert:";cin>>e1;ListInsert_L(L, place, e1);ShowList(L);cout<<"\nThe number of digits to be deleted:";int place1;cin>>place1;ListDelete_L(L, place1, temp);ShowList(L);printf("\nThe deleted node value is :%d\n", temp);LinkList Lb,Lc;cout<<"\nEnter the length of the linked list:";int num1;cin>>num1;CreateList_L(Lb, num1);//建表cout<<"\nThe two linked lists are:";MergeList_L(L,Lb,Lc);ShowList(L);cout<<endl;return0;}今天也是元⽓满满的⼀天!good luck!。

线性表的链式表示和实现—链表

线性表的链式表示和实现—链表
…… }
/*调用myList的析构函数*/
MyList的存储结构
(带头结点的空表)
head size 0
next NULL data
▪ 单链表求表长函数
int LinList<T>::Size(void) const {
return size; }
思考1:int LinList<T>::IsEmpty( ) const 如何实 现?——判断单链表空否
2.3.1 单链表的存储结构
◆ 结点结构:链表每个结点中只有一个指针 域指向直接后继结点。 data next 数据域 指针域
数据域:元素本身信息
指针域:指示直接后继的存储位置
结点类的定义 LinList.h文件实现单链表类
template <class T> class LinList; //前视定义,否则友元无法定义
//j从0开始计数
while(p != NULL && j < i) //寻找第i个结点
{ p = p->next; j++; }
return p;
//返回第i个结点的指针
} 思考2:ListNode<T> * LinList<T>::Find(T x) 如何实现?——
查找第一个值为x的元素在单链表的结点
单链表类的定义
template <class T>
class LinList
{
private:
ListNode<T> *head;
//头指针
int size;
//当前数据元素个数
ListNode<T> *Index(int i); //定位函数

数据结构-线性表链式存储结构

数据结构-线性表链式存储结构

04 线性表链式存储结构的实 现
C语言实现
创建链表
通过动态内存分配,创建链表节 点并逐个连接起来,形成链表。
插入节点
在链表指定位置插入节点,需要 更新插入位置节点的指针域,使 其指向新插入的节点。
删除节点
删除链表中的指定节点,需要更新被 删除节点前一个节点的指针域,使其 指向被删除节点的下一个节点。
01
遍历链表
从头节点开始,依次访问链表中的每 个节点,输出节点的数据值。
05
03
插入节点
在链表指定位置插入节点,需要更新 插入位置节点的引用,使其指向新插 入的节点。
04
删除节点
删除链表中的指定节点,需要更新被 删除节点前一个节点的引用,使其指 向被删除节点的下一个节点。
Python语言实现
在Python中,可以使
THANKS FOR WATCHING
感谢您的观看
适用场景
链式存储结构适用于需要频繁进行插入、删除等操作的数据结构,如动态数组、队列、链表等。
展望
01 02 03
未来发展方向
随着大数据和云计算的普及,数据结构的应用场景越来越 广泛,链式存储结构作为其中的一种重要形式,未来将有 更多的应用场景和优化空间。例如,针对大数据场景下的 链式存储结构优化、新型的链式数据结构等都是值得研究 的方向。
06 总结与展望
总结
定义与特点
链式存储结构是线性表的另一种存储方式,它通过在数据元素之间建立指针链接,实现了数据元素的逻辑顺序与物理 顺序的分离。相比于顺序存储结构,链式存储结构具有更好的动态性,能够方便地插入、删除等操作。
基本操作
链式存储结构支持的主要操作包括插入、删除、查找等,这些操作的时间复杂度通常为O(1)、O(n)、O(n),其中n为链表 长度。

实验五__线性表的链式表示和实现

实验五__线性表的链式表示和实现

浙江大学城市学院实验报告课程名称数据结构基础实验项目名称实验五线性表的链式表示和实现学生姓名专业班级学号实验成绩指导老师(签名)日期一.实验目的和要求1、了解线性表的链式存储结构,学会定义线性表的链式存储结构。

2、掌握单链表、循环单链表的一些基本操作实现函数。

二.实验内容1、设线性表采用带表头附加结点的单链表存储结构,请编写线性表抽象数据类型各基本操作的实现函数,并存放在头文件LinkList.h中(注:教材上为不带表头附加结点)。

同时建立一个验证操作实现的主函数文件test5.cpp,编译并调试程序,直到正确运行。

提示:⑴单向链表的存储结构可定义如下:struct LNode { // 定义单链表节点类型ElemType data; // 存放结点中的数据信息LNode *next; // 指示下一个结点地址的指针}⑵线性表基本操作可包括如下一些:①void InitList (LNode *&H) //初始化单链表②void ClearList(LNode *&H) //清除单链表③int LengthList (LNode *H) //求单链表长度④bool EmptyList (LNode *H) //判断单链表是否为空表⑤ElemType GetList (LNode *H, int pos)//取单链表第pos 位置上的元素⑥void TraverseList(LNode *H) //遍历单链表⑦bool InsertList ( LNode *&H, ElemType item, int pos)//向单链表插入一个元素⑧bool DeleteList ( LNode *&H, ElemType &item, int pos)//从单链表中删除一个元素⑶带表头附加结点的单链表初始化操作的实现可参考如下:void InitList(LNode *&H){ //构造一个空的线性链表H,即为链表设置一个头结点,//头结点的data数据域不赋任何值,头结点的指针域next则为空H=(LNode *)malloc(sizeof(LNode)); // 产生头结点Hif (!H) exit(0); // 存储分配失败,退出系统H->next=NULL; // 指针域为空}2、选做部分:编写一个函数void MergeList(LNode *&La, LNode *&Lb, LNode *&Lc),实现将两个有序单链表La和Lb合并成一个新的有序单链表Lc,同时销毁原有单链表La和Lb。

数据结构(二):线性表的链式存储结构

数据结构(二):线性表的链式存储结构

数据结构(⼆):线性表的链式存储结构1、为什么要使⽤链式存储结构?因为我们前⾯讲的线性表的顺序存储结构,他是有缺点的。

最⼤的缺点就是插⼊和删除时需要移动⼤量元素,这显然就需要耗费时间。

要解决这个问题,我们就需要分析⼀下为什么当插⼊和删除时,就要移动⼤量元素,因为相邻两元素的存储位置也具有相邻关系,它们在内存中的位置也是挨着的,中间没有空隙,当然就⽆法快速介⼊,⽽删除之后。

当中就会留出空隙,⾃然就需要弥补。

问题就出在这⾥。

为了解决这个问题,⾃然⽽然的就出现了链式存储结构。

2、线性表链式存储结构的特点:线性表的链式存储结构不考虑元素的存储位置,⽽是⽤⼀组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的,这就意味着,这些数据元素可以存在内存未被占⽤的任意位置。

顺序存储结构:只需要存储数据元素信息。

链式存储结构:除了要存储数据元素信息之外,还要存储⼀个指⽰其直接后继元素的存储地址。

3、关键词:数据域:存储数据元素信息的域。

指针域:存储直接后继位置的域。

指针或链:指针域中存储的信息。

结点(Node):指针域+数据域组成数据元素的存储映像。

头指针:链表中第⼀个结点的存储位置。

头节点:在单链表的第⼀个结点前附设⼀个结点,成为头结点。

头结点的数据域不可以存储任何信息,可以存储线性表的长度等附加信息,头结点的指针域存储指向第⼀个结点的指针。

4、单链表:定义:n个结点链成⼀个链表,即为线性表的链式存储结构,因此此链表的每个结点中只包含⼀个指针域,所以叫做单链表。

PS:线性链表的最后⼀个结点指针为“空”,通常⽤NILL或“^”符号表⽰。

头节点:在单链表的第⼀个结点前附设⼀个结点,成为头结点。

头结点的数据域不可以存储任何信息,可以存储线性表的长度等附加信息,头结点的指针域存储指向第⼀个结点的指针。

5、头结点与头指针的异同(1)头结点头结点是为了操作的统⼀和⽅便⽽设⽴的,放在第⼀个元素的结点之前,其数据域⼀般⽆意义(也可存放链表的长度)有了头结点,对第⼀元素结点前插⼊和删除第⼀结点,其操作就统⼀了头结点不⼀定是链表的必要素(2)头指针头指针式指向第⼀个结点的指针,若链表有头结点,则是指向头结点的指针。

第4讲 线性表的链式表示及应用

第4讲 线性表的链式表示及应用

Scanner scanner=new Scanner(System.in);
String str = scanner.next();
int i=0;
while(i<str.length()){
ch = str.charAt(i);
p= new Lnode(); //建立一个新结点p
p.data=ch;
操作成功,返回 TRUE.
int insertElementAt(int i,char x) {
Lnode p,s;
int j;
p=h;
j=0;
while(p!=null&&j<i-1) { //寻找第i-1号结点
p=p.next;
j++;
}
if(p!=null) {
s = new Lnode();
广东石油化工学院 理学院
16
8.循环链表
单循环链表 单链表中最后一个结点的链域值不是NULL, 而是指向头结点,整个表形成一个环
特点 从表中任意结点出发均可找到表中其它的结点
操作与单链表基本一致,循环条件不同 带头结点的单链表:p.next=null 带头结点的单循环链表:p.next=head
H
H
HH
…… ……
非空表非空表
广东石油化工学院 理学院
空空表表 17
9.单循环链表——查找算法
单循环链表的查找算法
在单循环链表中查找值为x的结点
public Lnode get(char x) { Lnode p; p=h.next; while (p!=h&&x!=p.data) //循环扫描查找,直到p 指向头结点h 或找到x结 p=p.next; if(p==h) return null; return p;

数据结构线性表的链式表示和实现(C语言)

数据结构线性表的链式表示和实现(C语言)

/*创建一个链表,实现对链表的创建,插入/追加,删除等操作*/# include <stdio.h># include <stdlib.h># include <malloc.h>//创建一个结构体typedef struct Node{int data;struct Node * pNext;}NODE,*PNODE;//函数前置声明PNODE create_list(void); //创建一个链表void traverse_list(PNODE); //遍历整个链表bool is_empty(PNODE); //判断列表是否为空int length_list(PNODE); //返回链表的长度bool insert_list(PNODE, int , int); //在链表中插入元素bool delete_list(PNODE, int, int *);//删除链表中的某个元素,并且返回被删除的元素的值。

void sort_list(PNODE); //对链表进行排序int main(void){//初始化头指针变量PNODE pHead = NULL;int val;//创建一个链表,将头结点的指针返回,保存到头指针变量中pHead = create_list();//判断这个链表是否为空/*if( is_empty(pHead) ){printf("这个链表为空\n");}else{printf("链表不为空\n");}*///查看元素的个数printf("该链表元素的个数为:%d\n",length_list(pHead));//遍历整个链表printf("遍历整个链表:");traverse_list(pHead);//插入元素printf("在第3个元素前插入一个99的值:");insert_list(pHead, 3, 99);traverse_list(pHead);//对链表进行排序printf("对链表进行升序排序:");sort_list(pHead);traverse_list(pHead);//删除链表中的元素printf("删除第三个位置的值:");delete_list(pHead, 3, &val);//遍历这个链表traverse_list(pHead);return 0;}/*常见一个链表@param void@return pHead 头指针*/PNODE create_list(void){int val; //用于保存用户输入的值int i; //for循环自增变量int data;//创建头结点PNODE pHead = (PNODE)malloc(sizeof(NODE));if(NULL == pHead){printf("动态内存创建失败\n");exit(-1);}PNODE pTail = pHead;pTail -> pNext = NULL;printf("需要创建元素的个数len=");scanf("%d",&val);for(i = 0; i < val; ++i){printf("请输入第%d个元素:", i + 1);scanf("%d",&data);//创建这个节点PNODE pNew = (PNODE)malloc(sizeof(NODE));if(NULL == pNew){printf("动态内存创建失败\n");exit(-1);}pNew -> data = data;pNew -> pNext = NULL;pTail -> pNext = pNew;pTail = pNew;}return pHead;}/*遍历一个链表@param PNODE 头指针@return void*/void traverse_list(PNODE pHead){PNODE p;p = pHead;if( is_empty(pHead) ){printf("这个链表为空\n");return;}while(NULL != p->pNext){p = p->pNext;printf("%d ",p->data);}printf("\n");}/*判断链表是否为空@param PNODE pHead 头指针@return bool*/bool is_empty(PNODE pHead){if( NULL == pHead -> pNext){return true;}else{return false;}}/*返回链表的长度@param PNODE pHead 头指针@return int i 指针的长度*/int length_list(PNODE pHead){PNODE p;int i = 0;if( is_empty(pHead) ){printf("链表为空。

浅析线性表的链式存储结构——链表

浅析线性表的链式存储结构——链表

插入算法 :
St at us I ns er t L (L i n k L i s t& L , { p = L ; j = 0 ; w h i l e (P & &j < i 一 1 ) {p = p 一 ) n e x t ; j + + ;} i f( P& &j := i 一 1 ) { s = ( L i n k L i s t )m a l l o c( s i z e o f( L N o d e ))

S - > d a t a= e ;s - > n e x t = p 一 > n e x t ;
p - > n e x t : s ;r e t u r n o k ; ) r e t u r n e r r o r ;} ( 二) 删 除。 在一个链表 中存在三个相邻 的数据域分别为 a ,b和 C的结点 ,通过删 除数据元素 b实现数据 元素 a ,b和 C 之间逻辑关系的变化 。 我们只需要改变结点 a中指针 的指 向, 让其指 向结点 c即可 。 假设 P为指 向结点 a的指针 ,则删 除过 程 的语 句为 :q = p 一 > n e x t ;p - > n e x t = q一 > n e x t ;f r e e ( q ) ; 删 除算 法: S t a t u s D e l e t eL (L i n k L i s t& L ,i n t i , E l e m T y p e& e ) { p = L ; j = 0 ;
消费 电子
计 算机科学
C o n s u me r E l e c t r o n i c s Ma g a z i n e 2 0 1 3年 4月 下
浅析线性表的链式存储结构
— —

数据结构论文--关于线性表的链式结构

数据结构论文--关于线性表的链式结构

数据结构课程小论文题目:线性表的链式表示学号:090510126姓名:叶妍莉班级:090510学院:经济管理学院2011年12月8日一.引言: --------------------------------------------------------------------- 2 - 二.链表的概述 --------------------------------------------------------------- 2 -1.线性链表里的一些概念: ------------------------------------------ 3 -2.链表的有关概述: --------------------------------------------------- 3 -3.链表的存储方法: --------------------------------------------------- 4 -4.链表的分类: --------------------------------------------------------- 4 - 三.线性表的链式实现 ------------------------------------------------------ 4 -1.“插入”和“删除”操作的实现: ------------------------------ 5 -2.“合并链表”操作的实现: --------------------------------------- 6 - 四.链表的优点与缺点 ------------------------------------------------------ 6 - 五.总结 ------------------------------------------------------------------------ 7 -线性表的链式表示姓名:叶妍莉班级:090510 学号:090510126摘要:线性表对于学过数据结构的人来说都是再熟悉不过了,它是数据结构的一个基本内容,是最常用且最简单的一种数据结构。

2-2基于链式存储的线性表的表示与实现

2-2基于链式存储的线性表的表示与实现

2-2基于链式存储的线性表的表⽰与实现2.4 基于链式存储的线性表的表⽰与实现(链表)⼀、线性表的链式存储结构线性表中的数据元素存放于内存分散的位置上。

由许许多多的结点链接⽽成。

结点 = 数据部分 + 指针(指向线性表中下⼀个结点的位置)头指针(不带头结点)头指针(带头结点)头结点①next 域存放什么?最后结点的标志:p->next=NULL 头指针是什么?参见P27图例,看书5分钟… …结点的动态配置,通过标准函数⽣成的,即p=( LNode*)malloc(sizeof(LNode));//函数malloc分配了⼀个类型为LNode的结点变量的空间,并将其⾸地址放⼊指针变量p中。

//函数free(p)释放所指的结点变量空间。

③⾮随机存取:取链表中第i个元素:设单链表的长度为n,要查找表中第i个元素,即第i个结点,仅当1≦i≦n时,i的值是合法的。

其算法如下:LNode* Getnode(LNode *L,int i) //L是带头结点的链表{LNode * p; int j;p=L; j=0; //初始化,p指向头结点,j为计数器while(p!=NULL&&j{ p=p->next;j++;}if (p==NULL || j>=i)printf(“第i个元素不存在!”);return p;}思考:(1)如果调⽤Getnode(L,0),结果如何?(2)⽐较:P29算法(3)时间复杂度:⼆、单链表的操作算法创建⼀个空的单链表求单链表的长度插⼊⼀个元素//最基本的操作删除⼀个元素//最基本的操作取某个位置的元素查找元素找某个元素的后继找某个元素的前驱两个链表合并……(1)插⼊运算假设1:在*p之后插⼊新结点*s:(插⼊在链表中间)单链表p插⼊结点图⽰:假设2:在*p之前插⼊?时间复杂度?假设3:插⼊在链表中第⼀个位置呢?假设4:如果链表是⼀个空表呢?特殊头结点LStatus ListInsert_L(LNode *L, int i, ElemType e){//在带头结点的单链表L中第i个位置插⼊元素eLNode *pre,*s;pre=Getnode(L,i-1); //找到第i-1个结点s=(LNode*)malloc (sizeof (LNode)); //⽣成新结点s->data=e;s->next=pre->next; pre->next=s; //插⼊L中return OK;}⽐较:不带头结点的单链表的插⼊操作if(L= =NULL) S->next=NULL;L=S; //空表if(i= =1) S->next=L; L=S; //在第⼀个位置插⼊if(i>1) P=Getnode(L,i-1); S->next=P->next;P->next=S;(2)删除运算//删除*p的后继结点://删除*P?Status ListDelete_L(LNode *L, int i, ElemType &e){ //在带头结点的单链线性表L中,删除第i个结点,并由e返回其值LNode *pre,*r;pre=Getnode(L,i-1); //找到第i-1个结点,即第i个节点的前⼀个结点prer=pre->next;pre->next=r->next; //删除并释放结点e=r->data;free(r);return OK;}删除P结点?(3)查找运算两种算法:status Getnode(Linklist L,int i, ElemType &e)LNode* Getnode(LNode *L,int i)(4)建⽴单链表链表是⼀个动态的结构,它不需要预先分配空间,因此⽣成链表的过程是⼀个结点“逐个插⼊”的过程。

实验二:线性表的链式表示和实现

实验二:线性表的链式表示和实现

实验二:线性表的链式表示和实现一、实验目的:1.掌握线性列表链式存储结构的表达与实现2.掌握对链表进行创建、插入、删除和查找等操作的算法。

3.掌握算法的设计与分析过程。

4.进一步熟悉VC++开发环境,熟悉应用程序的设计过程,掌握程序编辑、调试和集成的方法和技巧。

二、实验要求:1.采用教材中C语言描述的单链表存储结构,模块化设计流程,设计高效算法完成各种操作任务,并根据实际数据实现各种操作。

2.完成程序编写,调试成功后,书写实验报告。

三、实验任务:1.创建有n(n为正整数)数据元素的单链表,数据从键盘输入。

2.查找第i个结点,找到返回其值,否则返回0;3.对已经创建的单链表分别进行插入结点操作,在第i 个元素之前插入1个结点。

4.删除节点并删除第i个节点的元素。

5.在本地反转单链表。

6.将链表按值的奇偶数分解成两个链表。

要求:创建单链表后,其他操作可以是任意选择进行的。

(考虑设计菜单调用各功能模块)四、设计指南:1.结点的定义#include#includetypedefintdatatype;typedefstructnode{datatypedata;structnode*n ext;}lnode,*linklist;2.将复杂的问题分解成若干个相对容易的小问题,并设计好解决每个小问题的函数的函数名、入口参数及其返回值;设计出各个函数的程序框架及完整的主函数程序。

(注:每个功能一个函数)例如://输出链表数据voiddisplay(linklistl){linklistp;p=l->next;第1页/共3页而(p){printf(\p=p->next;}printf(\}//单链表初始化linklistlistinit(linklistl){l=(linklist)malloc(sizeof(lnode));l->next=null;returnl;}//创建单链表linklistlistcreate(linklistl,inta){inti;linklistp;//具体操作请大家自己完成display(l);returnl;}voidlistsearch(){}//单链表插入LinkListInsert(linklistl){linklistp,q;p=l;//具体操作请填写显示(L);returnl;}//单链表删除linklistlistdelete(linklistl){linklistp,q;p=l;//请自行完成具体操作voidmain(){第2页,共3页inti;inta,b,c;linklistl;l=listinit(l);while(1){printf(\单链表*****\\n\printf(\创建*****\\n\printf(\查找*****\\n\printf(\插入*****\\n\printf(\删除*****\\n\printf(\退出*****\\n\printf(\请输入您的选择:\\n\scanf(\switch(i){case1:printf(\请输入元素个数:\\n\scanf(\listcreate(l,a);break;case2:listsearch();break;case3:listinsert(l); break;case4:listdelete(l);display(l);break;case0:exit(0);default:printf(\您的输入有误,请重新输入!\\n\}}}第3页,共3页。

线性表的链式表示和实现讲解

线性表的链式表示和实现讲解
思路:要存取第i个数据元素,必须从头指针起一直找到 该结点的指针p,然后才能执行 p->data=new_value 。
访问第i个数据元素的操作函数可写为:
Status GetElem_L(LinkList L, int i, ElemType e) {p=L->next; j=1; //带头结点的链表
Q1:第一行的LNode 与最后一行的LNode是不是一回 事?
A1:不是。前者LNode是结构名,后者LNode是对整个 struct类型的一种“缩写”,是一种“新定义名”,它只 是对现有类型名的补充,而不是取代。
10
Q2: 那为何两处要同名(LNode和LNode)?太不严谨 了吧?
A2:同名是为了表述起来方便。因为描述的对象相同, 方便阅读和理解。 Q3:结构体中间的那个struct LNode是何意?
(1) 链式存储结构特点: 其结点在存储器中的位置是随意的,即逻辑上 相邻的数据元素在物理上不一定相邻。
如何实现? 通过指针来实现!
让每个存储结点都包含两部分:数据域和指针域
样式: 数据 指针 或 指针 数据 指针
数据域:存储 元素数值数据
指针域:存储直接后继或 者直接前驱的存储位置
设计思想:牺牲空间效率换取时间效率 3
13
(2) 单链表的插入(重点)
在链表中第i个位置前插入一个元素x 的示意图如下:
p
p
ai-1
ai
ai-1
ai
p->next
插入X
第2章 线性表
2.1 线性表的逻辑结构 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示和相加
1
2.3 线性表的链式表示和实现
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

头结点 复习:
a1
a2
p 结点
… ...
an ^
p 指针和 p 结点的区别: L是带头结点的链表的头指针,即L指向头结点,p为指针变 量,写出语句 p指向头结点: p指向第一个结点: p指向p结点的下一个结点: p=L p=L->next p=p->next
头指针
L
空指针
头结点
a1
a2
… ...
P=L; while (P!= NULL ) p=p->next; p=NULL
改进的 ClearList(L) :
p
L
///

^
void ClearList(LinkList L) { while (L->next) { p=L->next;
int LListlen(LinkList L ) { n=0; p=L ; while ( p->next ) { p=p->next; L->next=p->next; n++; } free(p) ; 算法时间复杂度: return n; } } } // ClearList O(ListLength(L))
Typedef struct LNode {ElemType data; // 数据域 struct Lnode *next; // 指针域 } LNode, *LinkList;
// LNode 为结构变量类型名, LinkList 为结构指针类型名 LinkList p;// p 为指针变量, 分配给 p 一个指针变量; p = (LinkList) malloc (sizeof (LNode)); p 或 p = (LNode*) malloc (sizeof (LNode));
2.3 线性表的链式表示和实现 顺序存储 优点:可随机存取 缺点:作插入和删除时,需移动大量元素
2.3.1 线性链表(单链表) 一. 单链表的概念 二、结点和单链表的 C 语言描述 三、线性表的操作在单链表中的实现 2.3.2 循环链表 2.3.3 双向链表
2.3.1 线性链表(单链表) 一. 单链表的概念
复习:数据结构在计算机中的表示(或映象)包括 “数据元素”的映象和“数据元素的关系”的映象。 用一组地址任意的存储单元(可连续可不连续) 存放线性表中的数据元素。 以 数据元素+ 指针(指示后继元素存储位置) = 结点 表示 数据元素的存储映象; n个结点链结成一个链表即为线性表的链式存储
结构。 若每个结点只包含一个指针域,则称为 ( 线性链表 )或 ( 单链表 )。
//直到p 指向第i-1个元素或p ->next为空
if (!( p->next ) || j > i-1 ) // i 大于表长或者小于1 return ERROR; // 删除位置不合理 q = p->next; p->next = q->next; // 删除q结点 *e = q->data; free(q); // 释放q结点
while (p && j < i-1) { p = p->next; ++j; }
if (!p || j > i-1)
// p 为空 ( i 大于表长+1)或者 i 小于1
return ERROR; s = (LinkList) malloc ( sizeof (LNode)); s->data = e; s->next = p->next; p->next = s; return OK; } // ListInsert_L (算法2.9)
所以算法2.8中有一条语句
if ( !p || j>i ) return ERROR; //第i个元素不存在
三、单链表操作的实现
GetElem(L, i, *e) // 取第i个数据元素 ListInsert(L, i, e) // 插入数据元素 ListDelete(L, i, e) // 删除数据元素 ClearList(L) // 重置线性表为空表 CreateList(L, n)
头指针
头结点
线性表为空表时, 头指针 头结点的指针域为空
空指针


a1
a2
图2.7
… ...
an ^
以线性表中第一个数据元素a1的存储地址作为线 性表的地址,称作线性表的头指针。 有时为了算法简单,在第一个结点之前增加一个 “头结点”,以指向头结点的指针为链表的头指针。
二、结点和单链表的 C 语言描述
算法的时间复杂度为: O(ListLength(L))
线性表的操作ListDelete (L, i, e)在链表中的实现: 在单链表中删除第 i 个结点的基本操作为: 1.找到线性表中第i-1个结点: p = L; j=0; while (p->next&& j < i-1) { p = p->next; ++j; }
二、输入数据元素an, 建立 p 结点并插入; p->next = L->next; L->next = p; 三、输入数据元素an-1, 建立 p 结点并插入; p->next = L->next; L->next = p; 四、依次类推,直至输入a1为止。 从 n 到 1 循环 n 次,可用 for 循环。
建立一个单链表。 逆序输入建立单链表分析: 1.建立一个空表(只有一个头结点); 2. i = n 到 1 { 输入 第i 个数据; 申请一个新结点并存放第 i 个数据值; 把该结点插入在头结点后; }
逆序输入 n 个数据元素的值, 建立带头结点的单链表。
操作步骤:
一、建立一个“空表”; L = (LinkList) malloc (sizeof (LNode)); L->next = NULL;
4. 插入: s->next = p->next; p->next = s;
ai-1 p
S
ai e
Status ListInsert_L(LinkList L, int i, ElemType e) { // L 为带头结点的单链表的头指针,本算法在链表中第i 个结点
// 之前插入新的元素 e
p = L; j = 0;
// 顺指针向后查找,直到p 指向第i个元素或p 为空
if ( !p || j > i ) return ERROR;
//第i个元素不存在,i太大 *e=p->data // 第i个元素赋给 e
return OK; } // GetElem_L(算法2.8)
问:若为顺序存储,如何实现? 只有一条语句:e = L.elem[i-1]
// 用p 指针申请一个 p 结点;
访问 p 结点内容
(*p).data , (*p).next 或 p->data , p->next
data next
A
LNode A;
//A为结点变量,分配给 A一个结点;
访问A 结点内容 A.data , A.next
data next
头指针
L
p
p 指针
空指针
while (p && j<i) { p = p->next; ++j; }
// 顺指针向后查找,直到p 指向第i个元素或p 为空
if ( !p) return ERROR;
*e=p->data
//第i个元素不存在,i太大
// 第i个元素赋给 e
return OK; } // GetElem_L
线性表的操作 ListInsert(L, i, e)在单链表中的实现: 在带头单链表中第 i 个结点之前进行插入的基本操作为:
// 顺指针向后查找,直到p 指向第 i 个元素或p 为空
while ( p && j < i-1 ) { p = p->next; ++j; }
//直到p 指向第i-1个元素或p 为空
while (p->next && j < i-1) { p = p->next; ++j; }
//直到p 指向第i-1个元素或p ->next为空
an ^
p
遍历单链表: P=L; while (P->next != NULL )
p=p->next; p 指针指向最后一个结点。 问循环结束时p 指针指向?
头指针
L
头结点
p
空指针
a1
a2
… ...
an ^
找单链表第 i 个结点: (1 <= i <=表长) P=L->next; j= 1; // p指向第一个结点,j为计数变量 while (P!= NULL && j < i ) { p=p->next; ++j ; } 有两种情况: (1) i < 1时没有循环,此时 j > i ; (2) i > 表长, 循环结束时 p=NULL ;或 !p;
算法2.8 j 的初值为1, 算法2.9和算法2.10 j 的初值为0 .
操作 ClearList(L) (重置L为空表)在链表中的实现: p
L
///

^
void ClearList(LinkList L) //将单链表L重新置为一个空表 { p = L->next ; L->next =NULL; while ( p ) { q = p->next; free( p ) ; p=q; } } // ClearList
相关文档
最新文档