【线性表】是具有相同数据类型的n个数据元素的有限序列,n=0是空表。即,表可以为空。
【a1】是唯一的“第一个元素”,又称“表头”。
【特性】
- 元素个数有限性
- 元素逻辑顺序性
- 数据类型同一性
- 元素内容抽象性
【区分】顺序表是存储结构连续,线性表是逻辑结构连续,注意区别
【线性表的表示】掌握:顺序表示和链式表示(即在计算机上,使用顺序和链式的存储结构表示线性关系)
【顺序表:线性表的顺序表示】「特点」逻辑顺序和物理顺序相同,地址连续,可以随机访问
【插入操作】将一个数据插入到第i个位置
【链式表示:单链表】
【单链表】是一种链式的线性表储存方式,通过一组人意的存储单元来存储线性表中的数据元素。为了建立起数据关系,需要一个指向它后一个元素的指针(后继指针)。
Data | Next—> |
Typedef structure Lnode{
ElemType data;
Struct Lnode *next;
}Lnode, *LinkList
【头插法】插到头结点的前面。如按12345的顺序依次在L->?️建立单链表,是L->5->4->3->2->1->?️。 单个结点插入O(1),总建立O(n)
【尾插法】插到链表尾部(增加表尾指针rear)
如按12345的顺序依次建立单链表,是L->?️->1->2->3->4->5。 单个结点插入O(1),总建立O(n)
【按序号查找】因为链表是地址的,序号只能用计数器来进行排号,在遍历的过程中进行计数,当计数器值和所给序号匹配时,停止遍历,输出对应数据域。
【按值查找】遍历,当匹配时输出对应数据域
遍历:p=p->next;
取值:x=p->data;
尾结点置空:r->next = NULL;
1⃣️ p结点后插s结点:s->next = p->next; p->= s;
2⃣️p结点前插s结点:遍历至p的前驱q,然后q结点后插s ,则实现. s->p
p结点前插s结点:无须遍历至p的前驱q;直接1⃣️,然后交换数据域(temp)(选择题)
【删除第i个】
或 无须遍历至前驱 :q = p->next ;p->data = q->data;p->next = q->next;free(q);(选择题)
【求表长】设置计数器进行遍历。有无头结点,计数器值不一样,注意区别;
【双链表】
单链表结点中只有一个指向其后继的指针,使得单链表只能从头到尾地一次顺序向后遍历,想要访问n的前一个结点,也需要从头开始遍历至p->next == n;才行。故引入双链表
L—>Prior | Data | Next |
Typedef struct Dnode{
ElemType data;
Struct Dnode *prior,*next;(递归定义,即prior也有data域和它自己的prior和next)
}Dnode, *Dlinklist;
【双链表的插入】
p后插入s
S->next = p->next; s指向p的后继
P->next->prior = s;p的后继的前驱指向s
S->prior= p;s的前驱指向s
P->next = s; p的后继指向s
【双链表的删除】
p->next = q->next;
P->next->prior = p;
Free(q);
题目:
- 单链表中,增加头结点目的是为了方便运算的实现☑️
- 线性表中每个元素都有一个直接前驱和后继❌ 头结点和尾结点就分别没有前驱和后继
- 取线性表第i个元素的时间与i的大小有关❌ 若使用顺序存储结构,则可以实现随机存取,与i无关
- 线性表:逻辑结构是线性的one by one 啊
- 带头结点的双链表【判空】L->next==L&&L->prior==L;
- 取线性表的第i个元素的时间同i的大小有关❌当使用顺序储存结构来实现的时候,就与i无关了
- 链表的每个结点恰好都有一个指针❌双链表就有两个
- 顺序储存结构属于静态结构,链式结构属于动态结构❌【静态链表】
- 具有头结点的链式储存结构,头指针指向链表中的第一个数据结点❌头指针->头结点,头结点->第一个
- 检查i的合法性
- 遍历p至第i-1的结点
- P->next = p->next->next; free (p->next);
- 单链表是非随机存取,不能直接找到表中的某个特定的结点(如果你知道地址?呵呵),必须从表头开始遍历,依次查找
- 通常用「头指针」来表示一个单链表,如单链表L,头指针为「NULL」时则表示一个空表
- 为了便于操作,在单链表之前附加一个结点称【头结点】:数据域可以不设置任何信息,也可利用起来记录表长,头指针的next指向第一个数据元素结点。
-
L—>
NULL
->
A1
->
A2
->
…->
An
->
- 【头结点优点】
- 由于开始结点的位置被存放在头结点的指针与中,所以在链表的第一个位置上的操作和在表上其他位置的操作一致了!第1个数据元素的位置就是a[1]的数据元素
- 无论链表是否为空,头指针都是指向头结点的(意味者头指针都是非空的),则表空或非空的操作就统一了
- 第n个元素 是a[n-1]的数据
- 线性表删除和插入、按值查找的平均时间复杂度为O(n),序号查找的O(1)
- 由于顺序表的插入和删除操作需要移动大量的元素,影响了运行效率,由此引入了线性表的「链式存储」。【链式存储线性表】,不需要使用地址连续的存储单元,即不要求逻辑上相邻的两个元素在物理位置上也相邻,他是通过“链”建立起来数据之间的逻辑关系,因此,对线性表的插入删除,仅需要修改指针即可
- 判断i的范围是否合法,if( i<1 || i>L.Length+1) return 0;
- 判断当前是否满表,if(L.Length >=MaxSize) return 0;
- 将第i个及其后边的元素,全往右移一个位置 for(int j=L.Length ; j>=I ;j- -) L.data[j]=L.data[j-1];
- 将新数据置于第i个位置上 L.data[i-1] = e;
- Length ++;
- return 1;
- 【特点】物理上相邻,插入和删除需要移动大量元素
- 线性表中元素的位序从1开始(a1、a2、a3…),数组中下表从0开始(a[0]、a[1]、a[2]…)
- 一维数组可以静态分配也可以,动态分配「再分配时,分配的仍是顺序结构」
- 【随机访问】通过首地址和元素序号在O(1)(一组运算)的时间内找到元素
- 【储存密度高达100%】因为顺序存储是以空间位置来表示逻辑关系,所以不需要另外的空间存放数据元素的逻辑关系,这样自然存储密度为100%了
- 元素个数有限性
- 元素逻辑顺序性
- 数据类型同一性
- 元素内容抽象性