什么是线性表?
线性表是n个类型相同的数据元素的有限序列,对n>0,除了第一元素无直接前驱、最后一个元素无直接后继外,其余的每个数据元素只有一个直接前驱和一个直接后继。
👍线性表的逻辑结构:
注意;
在一般的线性表中,一个数据元素可由若干个数据项组成。
姓名 | 学号 |
---|---|
张三 | 123 |
李四 | 456 |
表中,一行称为一个记录(或者数据元素),含有大量类型相同记录的线性表称为文件(或者数据对象)。
线性表的特点
同一性,线性表由同类数据元素组成,每一个元素必须属于同一个数据类型。
有穷性,线性表由有限个数据元素组成,表长度就是表中数据元素的个数。
有序性,线性表中相邻数据元素之间存在着序偶关系。
👍线性表的优点:
无需为表示表中元素间的逻辑关系而增加额外的存储空间,可以快速地存取表中任一位置的元素。
👍线性表的缺点:
插入、删除操作需要移动大量的元素。当线性表长度变化比较大时,难以确定存储空间的容量,会造成存储空间的碎片。
线性表的基本操作
操作 | 前提 | 结果 |
---|---|---|
InitList(L): | L为未初始化线性表 | 将L初始化为空表 |
ListLength(L) | 线性表L已经存在 | 如果L为空则返回表中的元素个数 |
GetData(L,i) | 表L已经存在,且1<=i<ListLength(L) | 返回线性表L中第i个元素的值 |
InsList(L,i,e) | 表L已存在,e为合法元素值且1<=i<=ListLength(L)+1 | 在L中第i个位置之前插入新的数据元素e,L长度加1 |
DelList(L,i,e) | 表L已存在且非空,1<=i<=ListLength(L) | 删除L的第i个数据元素,并用e返回其值,L的长度减1 |
Locate(L,e) | 表L已存在,e为合法数据元素值 | 如果L中存在数据元素e,则将当前指针指向数据元素e所在位置并返回TRUE,否则返回FALSE |
DestroyList(L) | 线性表L已存在 | 将L销毁 |
ClearList(L) | 线性表L已存在 | 将L置为空表 |
EmptyList(L) | 线性表L已存在 | 如果L为空表则返回TRUE,否则返回FALSE |
线性表的顺序存储
👍线性表的顺序存储指的是用一组地址连续的存储单元依次存储线性表中各个元素,使得线性表中在逻辑结构上相邻的数据元素存储在连续的物理存储单元中,即通过数据元素物理存储的连续性来反映数据元素之间逻辑上的相邻关系。
顺序表:关系线性化,结点顺序存。
顺序表以及后续的内容将在后面详细整理,通过简单的了解我们大概知道了什么是线性表,于是今天的一道例题已经够用!一起来解开这一道关于指针的题吧!!!😍😍😍
例题
设线性表L=(a1,a2,a3…,an-2,an-1,an)采用带头结点单链表保存,链表中结点定义如下:
typedef struct node
{
int data;
strut node *next;
}NODE;
设计一个算法,重新排序L中各个结点,得到线性表L‘=(a1,an,a2,an-1,…)。
答:
(❁´◡`❁) 思路:
先观察L=(a1,a2,a3…,an-2,an-1,an)和L’=(a1,an,a2,an-1,…)发现规律,就是依次排序第一个元素之后紧跟最后一个元素,然后第二个元素之后紧跟着倒数第二个元素依次执行完。为了方便链表后半段取元素,先将后半段元素原地逆置【可以借助栈,但为了减小空间复杂度不适用栈】。
💕💕💕方法思想:
1、先找出链表L的中间结点,为此设置两个指针p和q,指针p每次走一步,指针q每次走两步,当指针q到达链尾时,指针p正好在链表的中间结点。
2、然后将L的后半段结点原地逆置。
3、从单链表前后两端中依次各取一个结点,按要求重新排列。
算法实现:
void change_list(NODE *h
{
NODE *p,*q,*r,*s;
p=q=h;
while(q->next!=NULL){
p=q->next
q=q->next
if(q->next!=NULL){
q=q->next;
}
q=p->next;
p-next=NULL;
while(q!=NULL){
r=q->next;
q->next=p->next;
p->next=q;
q=r;
}
s=h->next;
q=p->next;
p->next=NULL;
while(q!=NULL){
r=q->next;
q->next=s->next;
s->next=q;
s=q->next;
q=r;
}
}
算法的时间复杂度:
第一步,找中间结点:O(1);
第二步,逆置后半段:O(n);
第三步,合并链表:O(n);
所以,整体算法的时间复杂度为:O(n).