线性表
分享的
线性表的基本操作
1、创建一个新的线性表
2、求线性表的长度
3、检索线性表中第i个数据元素(1 <=i<=n)
4、根据数据元素的某数据项(通常称为关键字)的值求该数据元素在线性表中的位置
5、在线性表的第i个位置上存入一个新的数据元素
6、在线性表的第i个位置上插入一个新的数据元素
7、删除线性表中第i个数据元素
8、对线性表中的数据元素按照某一个数据项的值的大小做升序或者降序排序
9、销毁一个线性表
10、复制一个线性表
11、按照一定的原则,将两个或者两个以上的线性表合并成一个线性表
12、按照一定的原则,将一个线性表分解为两个或两个以上的线性表
若假设每个数据元素占用k个存储单元,并且已知第一个元素的存储位置LOC(a1)则有
LOC(a1) = LOC(a1) + (i - 1)*k (公式)
在C语言中
#define MaxSize 100
ElemType A[MaxSize]; // 预先分配给线性表的空间大小
int n; // 表的长度
(1) 确定元素item在长度为n的顺序表A中的位置
(2)在长度为n的顺序表A的第i个位置上插入一个新的数据元素item
正常情况下需要做的工作:
1.将第i个元素至第n个元素依次后移一个位置
2.将被插入元素插入表的第i个位置
3.修改表的长度(表长增1) n++
需要考虑的异常情况:
1.是否表满? n = MaxSize ?
2.插入位置是否合适?(正常位置1<=i<=n+1)
约定:若插入成功,算法返回1 否则,算法返回-1
算法时间复杂度分析:通常采用元素移动次数的平均值作为衡量插入和删除算法时间效率的主要指标
(3)删除长度为n的顺序表A的第i个数据元素
把线性表的第i个数据元素从线性表中去掉,使得长度为n的线性表转换成长度为n-1的线性表
正常删除位置1<i<n
正常情况下需要做的工作
1.将第i+1个元素至n个元素依次前移一个位置
2.修改表的长度(表长减1)(n–)
需要考虑异常情况:
1.是否空表?n = 0?
2.删除位置是否合适?(正常位置1<=i<=m)
顺序存储结构的特点
1.优点
1.构造原理简单、直观,易理解
2.元素的存储地址可以通过一个简单的解析式计算出来。是一种随机存储结构,存储速度快。
3.由于只需存放数据元素本身的信息,而无其他空间开销,相对链式存储结构而言,存储空间开销小(仅此而已)
2.缺点
1.存储分配需要事先进行
2.需要一片地址连续的存储空间
3.基本操作(插入、删除)时间效率较低
链表
typedef struct node {
ElemType data;
struct node *link;
}LNode, *LinkList;
递归算法的时间效率通常比非递归算法要低
链表的基本操作
1.求线性表的长度
算法
非递归算法
int LENGTH(LinkList list)
{
LinkList p = list;
int n = 0;
while(p!=NULL) {
p = p->link;
n++;
}
return n;
}
递归算法
int LENGTH(LinkList list)
{
if(list!=NULL)
{
return 1 + LENGTH(list ->link)
} else
{
return 0;
}
}
2.建立一个线性表
// 申请一个链结点的控件
p = (LinkList)malloc(sizeof(LNode));
// 释放一个链结点的空间
free§;
LinkList CREATE(int n) {
LinkList p,r,list = NULL;
datatype a;
for(i = 1;i <=n;i++) {
READ(a);
p = (LinkList)malloc(sizeof(LNode));
p->data = a;
p->link = NULL;
if(list == NULL)
list = p;
else
r->link = p;
r = p;
}
return list;
}
3.在非空线性表的第一个结点前插入一个数据信息为item的新结点
void INSERTLINK1(LinkList &list, ELemType item)
{
/list指向链表的第一个链结点/
p = (LinkList)malloc(sizeof(LNode));
p - >data = item; // 将item送新结点数据域
p - >link = list; // 将list送新结点指针域
list = p; // 修改指针list的指向
}
4.在线性链表中由指针q指出的结点之后插入一个数据信息为item的链结点
void INSERTLINK2(LinkList &list, LinkList q, ElemType item)
{
LinkList p;
p = (LinkList)malloc(sizeof(LNode));
p - >data = item;
if (list == NULL) {
list = p;
p - >link = NULL;
} else {
p - >link = q -> link;
q ->link = p;
}
}
5.在线性表中第i个结点后面插入一个数据信息为item的链结点
void INSERTLIST3 (LinkList list, int i , ElemType item)
{
LinkList p,q,list;
int j;
for (j = 1;j < i - 1;j++)
{
q = q -> link;
if (q == NULL)
break; // 不存在第i个结点
}
p = (LinkList)malloc(sizeof(LNode));
p ->data = item;
p ->link = q ->link;
q ->link = p;
}
6.从非空线性链表中删除链结点q(q为指向被删除链结点的指针)
void DELETELINK1(LinkList &list, LinkList r, LinkList q)
{
if(q == list)
list = q ->link; // 删除链表的第一个链结点
else
r -> link = q->link; // 删除q指的链结点
free( q); // 释放被删除的空间
}
从非空线性链表中删除q指向的链结点
void DELETELINK2(LinkList &list, LinkList q)
{
LinkList r;
if(q == list) {
list = list->link;
free(q);
} else {
r = list;
while(r->link!=q && r->link!= NULL)
r = r ->link; // 移向下一个结点 寻找q结点的直接前驱r
if(r - >link != NULL) {
r -> link = q ->link;
free(q);
}
}
}
7.删除线性链表中满足某个条件的链结点
8.线性链表的逆转
9.将两个线性链表合并为一个线性链表
10.检索线性链表中的第i个链结点