数据结构之线性表

第二章 线性表

线性结构

特点:只有一个首结点和尾结点
除首尾结点外其他结点只有一个直接前驱和一个直接后继
一对一

定义

具有相同特性的数据元素所组成的有限序列

存储

顺序存储-顺序表

特点:逻辑上相邻,物理上也相邻,随机存取
结构体定义
typedef int ElemType;
typedef struct {
ElemType *elem; //数据元素基地址
int length; //线性表当前长度
}SqList;

重要的运算

插入(倒着插)
思想:例如在第i个元素之前插入一个元素,需要将第i个及其至之后的元素后移,将元素插入到第i-1个元素的位置,顺序表长度+1
算法(这里只写算法,不是可以运行成功)

void Insert(SqList &L,int i,ElemType x){
for(int j=L.length-1;j>=i-1;j--){
		L.elem[j+1]=L.elem[j];
		L.elem[i-1]=x;
		L.length++;
	}
}

总结:先移后插,长+1,平均移动次数n/2
删除(正着删)
思想:删除第i个元素,第一次将第i+1个元素取代第i个元素,依次将后一个元素取代前一个,顺序表长度-1
算法:

void Delete(SqList &L,int i,ElemType &x){
x=L.elem[i];
for(int j=i;j<=L.length-1;j++){
		L.elem[j]=L.elem[j+1];
		L.length--;
	}
}

总结:赋值前移长减一,平均移动次数(n-1)/2

链式存储-单链表

存储特点:逻辑上相邻,物理上不一定相邻,顺序存取
结构体定义:
typedef int ElemType;
typedef struct LNode{
ElemType data; //数据域
struct LNode *next; //指针域
}*LinkList;

重要的操作
插入

例如,将s指向的结点插入到p指向的结点之后
在这大睡大觉述
思想:s->next=p->next;p->next=s;
先将x结点和链表中b结点连接,在将a结点与x结点连接
需要注意的是插入过程中不要将链断开,这也就是先连后再连前的原因了

删除

例如将p指向结点的下一个结点删除
单链表删除
思想:p->next=p->next->next;
删除的话比较好理解,直接将a结点和b的后继结点相连,这样就成功的删除了b结点

建立单链表
头插法(带头结点)

思想:
生成新结点
将要插入的数据存到新结点的数据域中
将新结点插入到链表的前端
算法:

void CreateList(LinkList &L,int n){
LinkList p;
L =new LNode;
L->next=null;  //生成带头结点的单链表
for(int i=0;i<n;i++){
		p = new LNode;   //生成新结点
		cin>>p->data;   //输入要插入的元素值
		p->next=L->next;
		L->next=p;
	}
}
尾插法

思想:
新增一个尾指针r指向尾结点,
初始时尾指针和头指针同时指向头结点
**新生成一个结点,将输入的数据存入数据域,新结点插入到尾结点之后,尾指针实时指向尾结点。**循环操作
算法:

void CreateList(LinkList &L,int n){
LinkList p,r;
L =new LNode;
L->next=null;  //生成带头结点的单链表
r=L;       //头尾指针指向头结点
for(int i=0;i<n;i++){
		p = new LNode;   //生成新结点
		cin>>p->data;   //输入要插入的元素值
		r->next=p;      //新结点插入到表尾
		r=p;       //尾指针指向新的尾结点
	}
}

循环链表

定义:尾结点的指针域不再是空,而是指向链表头结点,整个链表形成一个环。(这里不作重点说明,重点掌握单链表)
特点:从任意结点出发都能访问到其他的结点。

双向链表

前面我们说到单链表,它的插入删除操作的时间复杂度都是O(1),但它访问某元素时的时间复杂度就是O(n),如果已知了一个元素,要删除它后面的元素,简单一步就做到了,时间复杂度就是O(1),但如果要删除它前面元素呢,就比较复杂了,此时指针已经指向这个元素,它是单向的,只能从前往后,由此引出双向链表。

定义:每个结点有两个指针域,分别指向它的前驱和后继结点
结构体定义:

typedef int ElemType;
typedef struct LNode{
ElemType data; //数据域
struct LNode *prior; //指向前驱结点
struct LNode *next; //指向后继结点
}*LinkList;

重要的操作
插入

前面我们说了单链表的插入和删除,这里呢,差不多意思。

例如:将x插入到a,b之间
双向链表插入
思想:正向插完,反向插,中间链不能断开。
s->next=p;
p->prior->next=s;
s->prior=p->prior;
p->prior=s;
另一种方法:左边连好,连右边,中间链不能断开
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;

删除

例:删除p所指的结点
双向链表删除
思想:正向删完,反向删
p->prior->next=p->next;
p->next->prior=p->prior;

顺序表与链表的比较

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值