C语言线性链表
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
表头结点
^
Status InitList_L(LinkList &L){ L=(LinkList)malloc(sizeof(LNode)); L->next=NULL;//创建头结点 return OK; }//InitList_L;
链表基本算法实现(2)——建立单链表
建立链表的过程是一个动态生成的过程: 从空表状态,依次建立各元素结点,并逐个插入
来自百度文库
单链表的插入操作
Step 1:s->next=p->next; Step 2:p->next=s ;
当!当!当! 万无一失吗??? 有没有问题呢?
6
单链表插入操作的特殊情况(1)
在第一个结点前插入 p
head a b ……
s
X
s->next 原语句: s->next=p->next; p->next=s ;
if (!p || j>i-1) return -1; //i值不合法
s = (LNode*) malloc( sizeof(LNode) ); //申请新结点的空间 s->data=e; s->next = p->next; p->next=s; //插入操作 return OK; } // ListInsert_L P29 算法2.9
总结:单链表的优缺点
优点
能有效利用存储空间; 用"指针"指示数据元素之间的后继关系,便于进 行"插入"、"删除"等操作;
缺点:
不能随机存取数据元素。 同时,还丢失了一些顺序表有的长处,如数据元 素在线性表中的“位序”,在的单链表中都“看 不见”了。 不便于在表尾插入元素,需遍历整个表才能找到 表尾。
27
coef
exp
方法3:用单链表实现
H a0 e0 a 1 e1 a2 e2 am em ^
typedef struct Poly_ListNode { float coef; //系数 int exp; //指数 struct Poly_ListNode *next; } Poly_ListNode ;
23
小结:顺序表和链表的比较
1. 选用原则
长度已知,且变化不大,则选择顺序表;
长度不定,或变化大,则选用链表。
1. 主要操作的特点
顺序表:插入、删除费时间移动数据, 取数据快速;
链表:插入、删除快速,取数据费时间。
24
2.4 线性表应用:一元多项式的表示和相加
多项式 (Polynomial)
P n ( x )=a 0 +a 1 x+a 2 x + ⋯ +an x
方法1实现:利用基本算法建立链表
LinkList CallFunc_CreatLinkList( ) { LinkList L; int i=0; InitList(L); //初始化链表 i=1; scanf(&x); while (x!=flag)//建立链表,flag结束标志 { ListInsert(L, i, x);//结点插入链表末尾 i++; 输入:67,23,10,45,36 scanf(&x); } 67 23 10 L return L; }
小结:带表头结点的单链表
表头结点位于表的最前端,本身不带数据,仅
做标志。有时可用来存储附加信息。 设置表头结点的好处: 以空间赢得时间 统一了链表第一位置和其他位置的操作;
统一了空表和非空表的操作;
使得各种链表(单向链表、双向链表、单向循
环链表和双向循环链表)的空链表状态得到区 分;亦表明各种空链表结构是不同的。
head
^
步骤:
(1)找到单链表的末尾; (2)将新结点插入。
尾插法
16
尾插法建立单链表算法
方法1:调用基本算法 建立链表; 思想: 1.初始化链表; 2.将结点逐个插入表尾
使用基本算法: void InitList(&L); void ListInsert(&L, i, e)
方法2:自编算法建立 思想: 1.初始化链表; 2.申请一个结点; 3.初始化它的值; 4.结点链入表尾; 5.结束否? 6.Yes,结束创建操作; 7.No,重复步骤2-6;
动态分配存储结构
#define LIST_INIT_SIZE 100 #define LISTINCREMENT 10 typedef int ElemType; typedef struct { ElemType *elem; int length; int listsize; } Sqlist;
方法2:尾插法建立单链表
int CreatListR(LinkList &H ) { int element; LinkList L; LNode *s, *last; //s指向新结点,last指向链表的最后结点 L=(LinkList)malloc(sizeof(LNode)); L->next=NULL; //建立头结点 last=L; cin>>element; while (element !=0) { s =(LNode *)malloc(sizeof(LNode)); //申请新结点 s ->data=element; s->next=NULL; last->next= s; //新结点链入链表 last=s; //last指向新的最后结点 cin>>element; } H=L; return 0; }// CreatListR 18
10
带表头节点单链表的插入操作
head p (1)表头插入: s X a
b
s->next=p->next; p->next=s ;
s->next
^
(2)空表插入: head p s
欧耶! 太给力了!!!
X
11
^
单链表插入操作的算法描述
status ListInsert_L( LinkList &L, int i, ElemType e ) { // 在带头结点的链表中的第i个结点前插入元素e p=L; j=0; while (p && j<i-1) { p=p->next; ++j; } //查找第i-1个结点
Note:只要不特殊说明,用的就是带头结点的链表。
13
课后作业
对照不带头结点和带头结点两种单链表
的插入操作,自行分析两种单链表对于 删除操作的不同。(书面作业)
说明:
必须要做! 虽然不讲,但是是考试内容!
14
2.3.3 链表基本算法实现(1)——初始化
生成一个带头结点的空链表
头指针 head
线性表的链式存储结构
每个元素由结点(Node)构成; 结点间的逻辑关系是线性的,即线性表; 结点在计算机中可以不连续存储; 链表可以扩充,只受存储介质大小的限制;
Node:
数据和数据间的关系分别存储
1
链表分类
按照链式存储的原则,可以有多种形式的链表
线性链表(单链表) 循环链表 双向链表
空表插入 head==NULL
s
核心语句: s->next=NULL; head =s ; 原语句: s->next=p->next; p->next=s ;
X
太麻烦了!!! 赶快想个办法吧!
9
he ad
解决之道:带表头结点的单链表
头指针
表头结点
head
头指针 head 表头结点
^
…
^
首结点:存储第一个数据元素
静态分配存储结构
#define ListSize 100 typedef struct { int number; char name[10]; int score; } Student; typedef struct { Student elem[ListSize]; int length; } Sqlist; #define ListSize 100 typedef int ElemType; typedef struct { ElemType elem[ListSize]; int length; } Sqlist; typedef struct { int number; char name[10]; int score; } Student;
rear
头结点 a1 an
H a1 a2 a3 an ^
单链表的定义
typedef int ElemType; typedef struct LNode{ ElemType data; //结点的数据域 struct LNode *next; //结点的指针域 }LNode, *LinkList;
2
n
= ∑ ai x i
i= 0
n
n阶多项式Pn(x)有n+1项。
系数为 a0, a1, a2, …, an x的指数为 0, 1, 2, …, n。按升幂排列
25
多项式的存储表示
方法1:按指数从0至n的次序保存所有项的系数。
每个数据项系数类型为 float, 多项式存储为 float coef [maxDegree];
问题:对于指数不全的多项式
如 P2000(x) = 3 + 5x 1000 – 14 x 2000 太浪费.
26
方法2:仅保存非0系数项的系数和指数
方法2:改进的顺序表
typedef struct { float coef; //系数 int exp; //指数 } Poly_node; Poly_node SqPoly[m+1];
3
单链表的存储映像
P
head
4
单链表的基本操作
初始化:InitList(&L) 销毁:DestroyList(&L) 清空:ClearList(&L) 判表空:ListEmpty(L) 求表长:ListLength(L) 取元素值:GetElem(L,i,&e) 查找某元素:LocateElem(L,e) 求前驱:PriorElem(L,cur_e,&pre_e) 求后继:NextElem(L,cur_e,&next_e) 插入:ListInsert(&L,i,e) 删除:ListDelete(&L,i,&e) 遍历:ListTraverse(L, Visit( ))
45
36 ^
尾插法建立单链表性能分析
T(n)=O(n) 如果不设last指针,则T(n)=O(n2) 不省心,总要记住表尾。 如何改进?
头插法
头插法建立单链表(P30 算法2.11)
void CreatList_L(LinkList &L, int n) { //逆位序输入n个元素的值,建立带头结点的单链表L L=(LinkList) malloc (sizeof(LNode) ); L->next=NULL; //建立头结点 for (i=n; i>0; - -i) { p=(LinkList)malloc(sizeof(LNode)); cin>>p->data; p->next=L->next; 输入:36,45,10,23,67 L->next=p; } 67 23 10 45 36 ^ L } CreatList_L
coef
exp
next
Poly_ListNode *SqPoly;
28
1.若学生记录信息为:[学号、姓名、成绩],要求
以顺序表实现。请分别以静态存储和动态存储两 种形式写出其数据结构描述。
#define ListSize 100 typedef int ElemType; typedef struct { ElemType elem[ListSize]; int length; } Sqlist; typedef struct { int number; char name[10]; int score; } ElemType;
22
其他类型的链表——双向链表
H a1 a2 a3 an ^
空表:
H
^
^
typedef int ElemType ; typedef struct DuLNode { ElemType data ; struct DuLNode *prior ; struct DuLNode *next ; } DuLNode, *DuLinkList ;
7
核心语句: s->next=p;//head; head=s ;
单链表插入操作的特殊情况(2)
在末尾插入
head a
p b
s
X
s->next
核心语句: s->next=NULL; p->next =s ;
8
原语句: s->next=p->next; p->next=s ;
单链表插入操作的特殊情况(3)