清华大学课件-链表的用法-PPT(全)
合集下载
课件-链表用法-全
} return head ; }
建立链表过程
初始状态 读入1后
head NULL
head
tail NULL
temp NULL
tail temp
1 NULL
建立链表过程
读入2后 head
1
读入3后
hea d
1
tail tem p
2 NULL
tail
tem p
2
3
NULL
9.2.2 单向链表的操作
9.2.2 单向链表的操作
建立单向链表
声明一个链首指针变量head,并赋初值 NULL(包含0个节点的链表)
动态分配一个新节点,将该节点链入链尾 重复上一步
例子1:建立链表,读入n个整数,每 个整数作为一个新结点插入到链尾
#include <iostream.h> struct node {
ቤተ መጻሕፍቲ ባይዱ
例子3:编写一个函数,在例1的链表 中查找包含指定整数的节点
node * findData(int n, node * head) {
node *curNode = head; while ( curNode ) {
if ( curNode->data == n) { cout<<"Find "<<n<<" in the list."<<endl; return curNode;
原链头节点的前驱指针指向新节点 新节点的后继指针指向原链头节点 新链头节点的前驱指针置为空指针
例子6:编写一个函数,按数据输入 的顺序建立双向链表
node *createBidirList (int n) { node *temp, *tail = NULL, *head = NULL ; int num; cin >> num; head = new node ; // 为新节点动态分配内存 if (head == NULL){ cout << "No memory available!"; return NULL; } else { head->data = num; head->next = NULL; head->pre = NULL; tail = head; }
建立链表过程
初始状态 读入1后
head NULL
head
tail NULL
temp NULL
tail temp
1 NULL
建立链表过程
读入2后 head
1
读入3后
hea d
1
tail tem p
2 NULL
tail
tem p
2
3
NULL
9.2.2 单向链表的操作
9.2.2 单向链表的操作
建立单向链表
声明一个链首指针变量head,并赋初值 NULL(包含0个节点的链表)
动态分配一个新节点,将该节点链入链尾 重复上一步
例子1:建立链表,读入n个整数,每 个整数作为一个新结点插入到链尾
#include <iostream.h> struct node {
ቤተ መጻሕፍቲ ባይዱ
例子3:编写一个函数,在例1的链表 中查找包含指定整数的节点
node * findData(int n, node * head) {
node *curNode = head; while ( curNode ) {
if ( curNode->data == n) { cout<<"Find "<<n<<" in the list."<<endl; return curNode;
原链头节点的前驱指针指向新节点 新节点的后继指针指向原链头节点 新链头节点的前驱指针置为空指针
例子6:编写一个函数,按数据输入 的顺序建立双向链表
node *createBidirList (int n) { node *temp, *tail = NULL, *head = NULL ; int num; cin >> num; head = new node ; // 为新节点动态分配内存 if (head == NULL){ cout << "No memory available!"; return NULL; } else { head->data = num; head->next = NULL; head->pre = NULL; tail = head; }
优秀的链表PPT课件
int i;
h=(JD*)malloc(sizeof(JD));
h->data=0;
算法描述
h->link=NULL; for(i=n;i>0;i--)
{s=(JD*)malloc(sizeof(JD));
s->data=a[i-1];
s->link=h->link;
h->link=s;
} return (h); 第9页
10单链表特点它是一种动态结构整个存储空间为多个链表共用不需预先分配空间指针占用额外存储空间不能随机存取查找速度慢请编程序建立一个带有头结点的单向链表链表结点中的数据通过键盘输入当输入数据为1时表示输入结束
链表
成俊燕 mail:zjucheng@
链表的定义
• 节点离散分布 • 节点之间通过指针连接 • 每个节点只有一个前驱,一个后继节点 • 首节点没有前驱,尾节点没有后继 • 术语
– 不需预先分配空间 – 指针占用额外存储空间 – 不能随机存取,查找速度慢
第11页
• 请编程序建立一个带有头结点的单向链表, 链表结点中的数据通过键盘输入,当输入 数据为-1时,表示输入结束。(链表头结点 的data域不放数据,表空的条件是ph-
>next==NULL).
• 有两个链表a和b。设结点中包含学号、姓 名。从a链表中删去与b链表中有相同学号 的那些结点。
第3页
例 线性表 (ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)
存储地址 数据域 指针域
头指针 H 31
H
1
LI
43
7
QIAN
13
13
SUN
1
六章节结构和链表-资料.ppt
}
9
6.2 结构的应用——链表
链表是一种线性表。一个线性表是n(n≥0)个数据元素的有限序 列。在计算机中,线性表可以选择连续存储和链接存储。
• 连续存储 把数据元素一个接一个地放在一组连续的存储单元之中,也就
是把线性表中的数据元素存放在一片连续的存储域。连续存储的线 性表称为数组。
因为数组的长度是固定的,而线性表的元素个数通常是不确定 的,所以通常将数组定义成充分大,但这样会造成存储空间的浪费。 用数组存储线性表的另一个缺点是在进行插入和删除操作时需要移 动数据。
{ char num[10]; int score; }c[N]; int i,s=0; for(i=0;i<N;i++) { cin>>c[i].num>>c[i].score; s=s+5*(c[i].score/100); //每100分换购5元商品 c[i].score=c[i].score-100*(c[i].score/100); //该会员的剩余积分 } cout<<"扣除积分后:\n"; for(i=0;i<N;i++) cout<<c[i].num<<'\t'<<c[i].score<<endl; cout<<"积分换购金额="<<s<<endl;
13
链表的常见操作有:
1. 建立链表; 2. 输出链表; 3. 确定链表的长度,即统计链表中结点的个数; 4. 查找链表中的某个结点; 5. 在链表中插入一个新的结点; 6. 删除链表中的某个结点。
94 58
NULL
9
6.2 结构的应用——链表
链表是一种线性表。一个线性表是n(n≥0)个数据元素的有限序 列。在计算机中,线性表可以选择连续存储和链接存储。
• 连续存储 把数据元素一个接一个地放在一组连续的存储单元之中,也就
是把线性表中的数据元素存放在一片连续的存储域。连续存储的线 性表称为数组。
因为数组的长度是固定的,而线性表的元素个数通常是不确定 的,所以通常将数组定义成充分大,但这样会造成存储空间的浪费。 用数组存储线性表的另一个缺点是在进行插入和删除操作时需要移 动数据。
{ char num[10]; int score; }c[N]; int i,s=0; for(i=0;i<N;i++) { cin>>c[i].num>>c[i].score; s=s+5*(c[i].score/100); //每100分换购5元商品 c[i].score=c[i].score-100*(c[i].score/100); //该会员的剩余积分 } cout<<"扣除积分后:\n"; for(i=0;i<N;i++) cout<<c[i].num<<'\t'<<c[i].score<<endl; cout<<"积分换购金额="<<s<<endl;
13
链表的常见操作有:
1. 建立链表; 2. 输出链表; 3. 确定链表的长度,即统计链表中结点的个数; 4. 查找链表中的某个结点; 5. 在链表中插入一个新的结点; 6. 删除链表中的某个结点。
94 58
NULL
链表的操作PPT课件
2、free_node()函数
void free_node(link p)
{
free(p);
第5页/共20页
3、insert()函数 void insert(link p) { p->next = head; head = p; }
第6页/共20页
4、delete()函数
void delete(link p) {
link p; for (p = head; p; p = p->next)
printf("%d\n", p->item); }
第8页/共20页
6、search()函数
link search(unsigned char key) {
link p; for (p = head; p; p = p->next)
• 链表的删除操作 LIST-DELETE'(L, x) • 增加哨兵节点后,忽视在表头和表尾的边界条件,代码变得更加简洁。 • 算法描述如下:
next[prev[x]] = next[x] prev[next[x]] = prev[x]
第19页/共20页
感谢您的观看!
第20页/共20页
第16页/共20页
1.2 双向链表
• 链表的搜索操作 LIST-SEARCH'(L, k) • 链表的搜索代码,对NULL和head[L]的引用做了改动。 • 算法描述如下:
x = next[nil[L]] while x ≠ nil[L] and key[x] ≠ k
do x = next[x] return x
x = head[L] while x ≠ NULL and key[x] ≠ k
C语言-链表(课堂PPT)
内存释放函数原形:void free(void *p); 功能:释放p所指向的内存块。
包含文件:malloc.h、stdlib.h中均有其原型声明。
C 程序设计
第十一章 结构体与共用体 NWPU—CC—ZhangYanChun
5
5) 采用链表的意义
与定长数据结构数组相比,链表能更好地利用 内存,按需分配和释放存储空间。
head
1048 p1 2101
1370 p1 2304
1012
2918
89.5
90
85
操作:
1370
1012
NULL
pp22
p2
p1=(struct student *)malloc(len); scanf("%ld,%f", &p1->num, &p1->score);
p2->next=p1; p2=p1; p2->next=NULL;
/*使p2也指向新节点*/ /*末尾节点next赋值0*/
C 程序设计
第十一章 结构体与共用体 NWPU—CC—ZhangYanChun
11
【例】建立并输出有3名学生数据的单链表。
#include <stdio.h> #include <math.h> #define N 3 struct student { long num;
int i, len; sqrt(5.5);
float score; struct student *next; }; void main( ) {┇ }
/*包含NULL的定义*/ /*结构体类型定义*/ /*自引用结构体指针*/
C 程序设计
61清华大学《数据结构》课程讲义第五讲PPT课件
叶子不会下沉,所以建堆过程应该从倒数第二层最右边一棵子树的根开始
建堆起点(数组下标起止)
树根r在数组 内的下标是0
a0
下一个子r递堆减起点
就是它的兄弟
子树根r的右
子树根r孩的子左下标 叶孩子子下下标标范围
a1
a3
n是节点总数
n 2
1
a4
a5
a2 起点
起点 a6
a7
a8 a9
a10 a11
a12 a13
int ttoottaall;
int grade;
char num[20];
stuGRADE AAA[[12[0390]]];
int SUBtotal;
char name[20];
struct node *left,*right;
student B[20];
};
};
};
大作业(三)--参考作业评判
数据结构
2012.2
课程大纲
第1讲 数据结构—应用、概念、以及课程基础 第2讲 线性表--链表、队列 第3讲 堆栈、非线性数据结构-二叉树 第4讲 二叉树、堆 第5讲 堆、哈夫曼树 第6讲 检索操作 第7讲 分块检索与哈希表 第8讲 排序 第9讲 算法分析与图的基本概念 第10讲 图结构 第11讲 图应用 第12讲 高级数据结构内容--索引技术
得庞大;
2. 平衡处理的很好。
3. 层次遍历不错,这次删除了线索化 二叉树的内容,有条件的同学可以 自己做。
4. 统计界面不错。
十字链参考
堆结构 局部有序:有序关系仅限定在
父亲与孩子之间,任何一个节 点与其兄弟之间的关键码值大
a1
小都没有必然的联系
一堆元素有顺序 的聚集在一起
建堆起点(数组下标起止)
树根r在数组 内的下标是0
a0
下一个子r递堆减起点
就是它的兄弟
子树根r的右
子树根r孩的子左下标 叶孩子子下下标标范围
a1
a3
n是节点总数
n 2
1
a4
a5
a2 起点
起点 a6
a7
a8 a9
a10 a11
a12 a13
int ttoottaall;
int grade;
char num[20];
stuGRADE AAA[[12[0390]]];
int SUBtotal;
char name[20];
struct node *left,*right;
student B[20];
};
};
};
大作业(三)--参考作业评判
数据结构
2012.2
课程大纲
第1讲 数据结构—应用、概念、以及课程基础 第2讲 线性表--链表、队列 第3讲 堆栈、非线性数据结构-二叉树 第4讲 二叉树、堆 第5讲 堆、哈夫曼树 第6讲 检索操作 第7讲 分块检索与哈希表 第8讲 排序 第9讲 算法分析与图的基本概念 第10讲 图结构 第11讲 图应用 第12讲 高级数据结构内容--索引技术
得庞大;
2. 平衡处理的很好。
3. 层次遍历不错,这次删除了线索化 二叉树的内容,有条件的同学可以 自己做。
4. 统计界面不错。
十字链参考
堆结构 局部有序:有序关系仅限定在
父亲与孩子之间,任何一个节 点与其兄弟之间的关键码值大
a1
小都没有必然的联系
一堆元素有顺序 的聚集在一起
C语言_链表ppt课件
} 许多问题中,有时候为了操作方便,需要在第一个节点之前增加一个
特殊的节点,称为头节点,它的data字段不含信息或根据问题的需要 存放特殊信息。
2、链表的遍历(显示链表)
一个非递归算法
以下函数disp()用于显示头节点为*h的链表的所有节点 数据域。
void disp(struct Node *h) { struct Node *p=h; printf("输出链表:"); if(p==NULL) printf("空表\n"); else { while (p->next!=NULL) { printf("%4d",p->data); p=p->next; } printf("%4d\n",p->data); }
在链表结尾出插入一个元素
p
data
首先要用一个循环语句找到q
q
q=h;
h
...
NULL
while(q->next!=NULL)
q=q->next;
p
然后执行插入语句:
data
p->next=NULL;
q
q->next=p;
h
...
NULL
p
data
q
h
...
NULL
在链表中间插入一个元素
p
data
}
单链表的插入
.
3、链表的插入(头指针的情况下)
对于插入有以下几种情况 在一个空链表上插入一个元素。 (即要插入位置前方和后方均无元素) 从链表表头处插入一个元素 (即要插入的位置前方无元素,后方有元素) 从链表结尾处处插入一个元素 (即要插入的位置后方五元素,前方有元素) 从链表的中间插入 (即要插入的位置前方和后方均有元素) 其中第三种情况可以按照第四种情况处理,但有一定特殊性所以将 其分开 注意:产生新的节点必须用malloc或者calloc开辟空间
特殊的节点,称为头节点,它的data字段不含信息或根据问题的需要 存放特殊信息。
2、链表的遍历(显示链表)
一个非递归算法
以下函数disp()用于显示头节点为*h的链表的所有节点 数据域。
void disp(struct Node *h) { struct Node *p=h; printf("输出链表:"); if(p==NULL) printf("空表\n"); else { while (p->next!=NULL) { printf("%4d",p->data); p=p->next; } printf("%4d\n",p->data); }
在链表结尾出插入一个元素
p
data
首先要用一个循环语句找到q
q
q=h;
h
...
NULL
while(q->next!=NULL)
q=q->next;
p
然后执行插入语句:
data
p->next=NULL;
q
q->next=p;
h
...
NULL
p
data
q
h
...
NULL
在链表中间插入一个元素
p
data
}
单链表的插入
.
3、链表的插入(头指针的情况下)
对于插入有以下几种情况 在一个空链表上插入一个元素。 (即要插入位置前方和后方均无元素) 从链表表头处插入一个元素 (即要插入的位置前方无元素,后方有元素) 从链表结尾处处插入一个元素 (即要插入的位置后方五元素,前方有元素) 从链表的中间插入 (即要插入的位置前方和后方均有元素) 其中第三种情况可以按照第四种情况处理,但有一定特殊性所以将 其分开 注意:产生新的节点必须用malloc或者calloc开辟空间
-链表的操作教学课件-
链表的插入有三种情况
插入的节点可以在表头、表中或表尾。
链表的插入
假定我们按照以学号为顺序建立链表,则插入的节点依次 与表中节点相比较,找到插入位置。 由于插入的节点可能在链表的头,会对链表的头指针造成 修改,所以定义插入节点的函数的返回值定义为返回结构 体类型的指针。
结点的插入函数
if (n<=p2->num) / *找到插入位置* /
LOGO
Teacher teaching design
链表的基本操作(建立、输出、插入新结点、删除结点)
目 录 CONTENTS
链表的创建 链表的结点插入 链表的结点删除 链表的输出
创建单向链表
PART 01
创建单向链表
1
定义链表的数据结构。
2 3 4 45
创建一个空表
利用malloc( )函数向系统申请分配一个结点。
p=p->next; k++; } if (k!=i-1)
printf(“删除结点的位置i不合法”); else { q=p->next;
p->next=q->next; free(q); } }
案例分析 交流提升
PART 04
添加标题内容
建立如图所示的存储结构(即每个节点两个域,data是数据域,next是指向节点的指针域,请将定义补充完整)。
p=s; q=p->next; r=q->next;
sum+=q->next->num;
sum+=r->next->next->num;
printf("%d\n", sum);
}
已知head指向单链表的第一个节点,以下程序调用函数print输出这一单向链表。请在选择正确内容填空。
语言链表详解ppt课件.ppt
6
火灾袭来 时要迅 速疏散 逃生, 不可蜂 拥而出 或留恋 财物, 要当机 立断, 披上浸 湿的衣 服或裹 上湿毛 毯、湿 被褥勇 敢地冲 出去
(4)删除操作是指,删除结点ki,使线性表的长度 减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变 化:
删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1 成为ki+1的前驱,ki+1成为ki-1的后继.
c.num=99107 ; c.score=85; 态链表”
个
head=&a; a.next=&b; b.next=&c; c.next=NULL; 简
p=head;
单
do
链 表
{ printf("%ld %5.1f\n",p->num,p->score);
p=p->next; }while(p!=NULL); }
scanf("%1d,%f",&p1->num,&p1->score); head=NULL; 假设头指向空结点
20
火灾袭来 时要迅 速疏散 逃生, 不可蜂 拥而出 或留恋 财物, 要当机 立断, 披上浸 湿的衣 服或裹 上湿毛 毯、湿 被褥勇 敢地冲 出去
while(p1->num!=0) { n=n+1;
10
火灾袭来 时要迅 速疏散 逃生, 不可蜂 拥而出 或留恋 财物, 要当机 立断, 披上浸 湿的衣 服或裹 上湿毛 毯、湿 被褥勇 敢地冲 出去
2. calloc 函数
函数原形:void *calloc(unsigned n,unsigned size); 作用:在内存动态区中分配 n个 长度为size的
火灾袭来 时要迅 速疏散 逃生, 不可蜂 拥而出 或留恋 财物, 要当机 立断, 披上浸 湿的衣 服或裹 上湿毛 毯、湿 被褥勇 敢地冲 出去
(4)删除操作是指,删除结点ki,使线性表的长度 减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变 化:
删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1 成为ki+1的前驱,ki+1成为ki-1的后继.
c.num=99107 ; c.score=85; 态链表”
个
head=&a; a.next=&b; b.next=&c; c.next=NULL; 简
p=head;
单
do
链 表
{ printf("%ld %5.1f\n",p->num,p->score);
p=p->next; }while(p!=NULL); }
scanf("%1d,%f",&p1->num,&p1->score); head=NULL; 假设头指向空结点
20
火灾袭来 时要迅 速疏散 逃生, 不可蜂 拥而出 或留恋 财物, 要当机 立断, 披上浸 湿的衣 服或裹 上湿毛 毯、湿 被褥勇 敢地冲 出去
while(p1->num!=0) { n=n+1;
10
火灾袭来 时要迅 速疏散 逃生, 不可蜂 拥而出 或留恋 财物, 要当机 立断, 披上浸 湿的衣 服或裹 上湿毛 毯、湿 被褥勇 敢地冲 出去
2. calloc 函数
函数原形:void *calloc(unsigned n,unsigned size); 作用:在内存动态区中分配 n个 长度为size的
双向循环链表--清华大学课程讲义-数据结构(PPT)
2013-9-10 4
2013-9-10
5
2013-9-10 2
带头结点的双向循环链表 :
first
e0
e1
current
…
en-1
first 空表 游标结点: * current 游标结点的前驱结点: * ( current -> lLink ) 游标结点的后继结点: * ( current -> rLink )
2013-9late <class Type> class DblList { public: DblList ( Type uniqueVal ); ~DblList ( ); int Length ( ) const; int IsEmpty ( ) { return first->rLink==first ;} int Find ( const Type & target ); Type getData ( ) const; void Firster ( ) { current = first; } int First ( ); int Next ( ); int Prior ( ); int operator ! ( ) { return current != NULL;} void Insert ( const Type & value ); void Remove ( ) ; private: DblNode <Type> * first, * current; }
调查结果:
讲课进度: 偏快 27 人 适中 20 人 偏慢 2 人 课程难易: 太简单 1 人 偏难 9 人 太繁 1 人 讲解方法: 多讲理论、原理、方法,少讲具体程序 少讲理论,多讲程序和C++内容 多讲具体应用的完整实例 其他: 规定交作业时间,促进学生做作业; 作业太多,要少而精; 最好能现场编程、调试;
2013-9-10
5
2013-9-10 2
带头结点的双向循环链表 :
first
e0
e1
current
…
en-1
first 空表 游标结点: * current 游标结点的前驱结点: * ( current -> lLink ) 游标结点的后继结点: * ( current -> rLink )
2013-9late <class Type> class DblList { public: DblList ( Type uniqueVal ); ~DblList ( ); int Length ( ) const; int IsEmpty ( ) { return first->rLink==first ;} int Find ( const Type & target ); Type getData ( ) const; void Firster ( ) { current = first; } int First ( ); int Next ( ); int Prior ( ); int operator ! ( ) { return current != NULL;} void Insert ( const Type & value ); void Remove ( ) ; private: DblNode <Type> * first, * current; }
调查结果:
讲课进度: 偏快 27 人 适中 20 人 偏慢 2 人 课程难易: 太简单 1 人 偏难 9 人 太繁 1 人 讲解方法: 多讲理论、原理、方法,少讲具体程序 少讲理论,多讲程序和C++内容 多讲具体应用的完整实例 其他: 规定交作业时间,促进学生做作业; 作业太多,要少而精; 最好能现场编程、调试;
精品-清华大学C语言课件 第13章03 链表的相关操作
该函数的功能是在内存中动态分配n个长度为size的连续内存空间数组。calloc函数会返回一个指针,该 指针指向动态分配的连续内存空间地址。当分配空间错误时,返回NULL。 free函数 其函数的原型如下:
void free( void *ptr );
函数的功能使用由指针ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用 calloc或malloc函数时返回的值。free函数无返回值。
图13.9 删除结点操作 通过上面的图示可以发现要删除一个结点,首先要找到这个结点的位置,例如图中的NO2结点。然后 将NO1结点的指针指向NO3结点,最后将NO2结点的内存空间释放掉,这样就完成了结点的删除操作。
根据这种思想编写删除链表结点操作的函数:
/*pHead表示头结点,iIndex表示要删除的结点下标*/ void Delete(struct Student* pHead,int iIndex) { int i; /*控制循环变量*/ struct Student* pTemp;/*临时指针*/ struct Student* pPre;/*表示要删除结点前的结点*/ pTemp=pHead;/*得到头结点*/ pPre=pTemp; printf("----删除成员%d ----\n",iIndex);/*提示信息*/ for(i=1;i<iIndex;i++)/*for循环使得pTemp指向要删除的结点*/ { pPre=pTemp; pTemp=pTemp->pNext; } pPre->pNext=pTemp->pNext;/*连接删除结点两边的结点*/ free(pTemp);/*释放掉要删除结点的内存空间*/ iCount--;/*减少链表中的元素个数*/ }
void free( void *ptr );
函数的功能使用由指针ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用 calloc或malloc函数时返回的值。free函数无返回值。
图13.9 删除结点操作 通过上面的图示可以发现要删除一个结点,首先要找到这个结点的位置,例如图中的NO2结点。然后 将NO1结点的指针指向NO3结点,最后将NO2结点的内存空间释放掉,这样就完成了结点的删除操作。
根据这种思想编写删除链表结点操作的函数:
/*pHead表示头结点,iIndex表示要删除的结点下标*/ void Delete(struct Student* pHead,int iIndex) { int i; /*控制循环变量*/ struct Student* pTemp;/*临时指针*/ struct Student* pPre;/*表示要删除结点前的结点*/ pTemp=pHead;/*得到头结点*/ pPre=pTemp; printf("----删除成员%d ----\n",iIndex);/*提示信息*/ for(i=1;i<iIndex;i++)/*for循环使得pTemp指向要删除的结点*/ { pPre=pTemp; pTemp=pTemp->pNext; } pPre->pNext=pTemp->pNext;/*连接删除结点两边的结点*/ free(pTemp);/*释放掉要删除结点的内存空间*/ iCount--;/*减少链表中的元素个数*/ }
链表的基本操作
pt=creat(); printf("\nnum:%ld
\nscore:%5.1f\n",
pt->num,pt->score);
}
struct Student *creat()
{ struct Student *head,*p1,*p2; n=0;
p1=p2=( struct Student*) malloc(LEN);
使p后移一个结点
p
1001
67.5
1003 87
1005 99
NULL
➢解题思路:
输出p所指的结点
printf("%ld %5.1f\n",p->num,p->score); 使p后移一个结点
p=p->next; p
1001 67.5
1003 87
1005 99
NULL
➢解题思路:
输出p所指的新结点 printf("%ld %5.1f\n",p->num,p->score);
p1=(struct Student*)malloc(LEN); scanf("%ld,%f",&p1->num,&p1->score);
head
10101 89.5
p2
p1
10103 90
10107 85
解题思路:
使第二个结点的next成员指向第三个结点,即 连接第二个结点与第三个结点
p2->next=p1; 使p2指向刚才建立的结点
scanf("%ld,%f",&p1->num,&p1->score);
\nscore:%5.1f\n",
pt->num,pt->score);
}
struct Student *creat()
{ struct Student *head,*p1,*p2; n=0;
p1=p2=( struct Student*) malloc(LEN);
使p后移一个结点
p
1001
67.5
1003 87
1005 99
NULL
➢解题思路:
输出p所指的结点
printf("%ld %5.1f\n",p->num,p->score); 使p后移一个结点
p=p->next; p
1001 67.5
1003 87
1005 99
NULL
➢解题思路:
输出p所指的新结点 printf("%ld %5.1f\n",p->num,p->score);
p1=(struct Student*)malloc(LEN); scanf("%ld,%f",&p1->num,&p1->score);
head
10101 89.5
p2
p1
10103 90
10107 85
解题思路:
使第二个结点的next成员指向第三个结点,即 连接第二个结点与第三个结点
p2->next=p1; 使p2指向刚才建立的结点
scanf("%ld,%f",&p1->num,&p1->score);
10-链表-清华
head p1
num score
p1 head
则可通过不断地在表头或表尾加入结点来生成链表。
1.在表头加入一个结点:
head=NULL; p1=(struct student *)malloc(LEN); scanf("%ld%f",&p1->num,&p1->score); p1->next=head; head=p1;
4.插入结点──插入s所指的结点在p所指结点之后
head
data next data
data next
data next
p
data next data next
s
data next
data NULL next s data NULL next
head
s->next=p->next; next p->next=s;
next num score
next num
反复以上做法,链表可从表尾向 表头一直延伸,head总指向表头。
p1
head
score
2.在表尾加入结点,建立链表
head=NULL; p1=p2=(struct student *)malloc(LEN); scanf("%ld%f",&p1->num,&p1->score); n=0; while(p1->num!=0) {n++; if(n==1)head=p1); else p2->next=p1); p2=p1; p1=(struct student *)malloc(LEN); scanf("%ld%f",&p1->num,&p1->score); } p2->next=NULL; free(p1); p1=head;
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
next:指向下一个node类型的结构,连接node 的纽带 28 52 2 96 NULL
5
head
2013-9-25
9.2.1 单向链表定义
存放学生信息的链表节点
struct student { int num; char name[20]; char sex; float score; student * next; };
12
9.2.2 单向链表的操作
遍历链表
依次访问链表中的每个节点的信息 head->data = 15; head->next->data = 15; 一般遍历方法 node * curNode = head; while (curNode ) curNode = curNode->next;
第9章 链表
2013-9-25
1
讲授内容
自引用结构、链表的概念 内存的动态分配和释放 单向链表的定义与操作 双向链表的定义与操作
2013-9-25
2
9.1 链表的基本概念
结构数组--必须将数组的大小设定成足 够大的值
太浪费 能否需要多少分配多少?
链表 = 动态内存分配 + 结构 + 指针
17
例子4:编写一个函数,将输入的整数 从小到大插入链表
newNode->data = n; if (preNode == NULL) //插入到链表头 { newNode->next = curNode; return newNode; } else { preNode->next = newNode; newNode->next = curNode; return head; }
2013-9-25
22
9.3.1 双向链表的定义
双向链表的例子:
28 52 2 96 NULL NULL
head
双向链表一般也由头指针唯一确定 双向链表首尾相接可以构成双向循环链 表
23
2013-9-25
9.3.2 双向链表的操作
建立双向链表
新节点链入链尾
原链尾节点的后继指针指向新节点 新节点的前驱指针指向原链尾节点 新链尾节点的后继指针置为空指针 原链头节点的前驱指针指向新节点 新节点的后继指针指向原链头节点 新链头节点的前驱指针置为空指针
2013-9-25
19
例子5:编写一个函数,删除链表中包 含指定整数的节点
node * deleteData(int n, node * head) { node *curNode = head;// 指向当前节点 node *preNode = NULL;// 指向当前节点的前驱节点 while (curNode && curNode->data != n) { preNode = curNode; // 当前节点变为前驱节点 curNode = curNode->next; } if (curNode == NULL) { cout<<"Can't find "<<n<<" in the list"<<endl; return head; } if (preNode == NULL) //删除链首节点 head = head->next; else preNode->next = curNode->next; delete curNode; return head; // 返回链首指针 20 } 2013-9-25
}
26
9.3.2 双向链表的操作
双向链表的遍历
有链首节点,则可以沿着后继指针从 头至尾遍历 有链尾节点,则可以沿着前驱指针从 尾向头遍历
2013-9-25
27
例子7:编写一个函数,输出双向链表 中各节点的data成员的值
void outputBidirList(node * head) { cout << "List: "; node *curNode = head; while ( curNode ) { if (curNode ->pre) cout << " <- "; cout << curNode->data; if (curNode ->next) cout << " -> "; curNode = curNode ->next; } cout << endl; return; }
2013-9-25 25
例子6:编写一个函数,按数据输入的 顺序建立双向链表
for ( int i = 0; i < n - 1; i ++) { cin >> num; temp = new node ; // 为新节点动态分配内存 if (temp == NULL) { cout << "No memory available!"; return head; } else { temp->data = num; temp->next = NULL; temp->pre = tail; tail->next = temp; tail = temp; } } return head ; 2013-9-25
9.3 双向链表
单向链表:有利于从链首向链尾遍 历 有些时候双向遍历是需要的——双向 链表
2013-9-25
21
9.3.1 双向链表的定义
定义双向链表的节点:
struct node { int data; node * next; node * pre; };
//指向后续节点 //指向前面的节点
14
例子3:编写一个函数,在例1的链表 中查找包含指定整数的节点
node * findData(int n, node * head) { node *curNode = head; while ( curNode ) { if ( curNode->data == n) { cout<<"Find "<<n<<" in the list."<<endl; return curNode; } curNode = curNode->next; } cout<<"Can't find "<<n<<" in the list."<<endl; return NULL; 15 } 2013-9-25
例子1:建立链表,读入n个整数,每 个整数作为一个新结点插入到链尾
node *createList(int n) { node *temp, *tail = NULL, *head = NULL ; int num; cin >> num; head = new node ; // 为新节点动态分配内存 if (head == NULL) { cout << "No memory available!"; return NULL; } else { head->data = num; head->next = NULL; tail = head; } 2013-9-25
9
例子1:建立链表,读入n个整数,每 个整数作为一个新结点插入到链尾
for ( int i = 0; i < n - 1; i ++) { cin >> num; temp = new node ; // 为新节点动态分配内存 if (temp == NULL) { cout << "No memory available!"; return head; } else { temp->data = num; temp->next = NULL; tail->next = temp; tail = temp; } } return head ;
例子4:编写一个函数,将输入的整数 从小到大插入链表
node * insertData(int n, node * head) { node *curNode = head;// 指向插入点的后节点 node *preNode = NULL;// 指向插入点的前节点 node *newNode = NULL;// 指向新建节点 while ((curNode!=NULL)&&(curNode->data<n)) { preNode = curNode; // 后节点变为前节点 curNode = curNode->next; } newNode = new node ; if (newNode == NULL) { cout << "No memory available!"; return head; } 2013-9-25
10
} 2013-9-25
建立链表过程
初始状态 head
tail NULL tail
temp
NULL
head
NULL
temp
读入1后
1 NULL
2013-9-25
11
建立链表过程
读入2后
head tail
temp
1 读入3后 head
2 NULL tail temp
1
2013-9-25
2