- 昨天梳理了数据结构第一章绪论的知识点和算法时空复杂度的估算问题。今天这篇是对线性表的知识梳理。
线性结构
1)存在唯一一个“第一元素”和唯一一个“最后元素”
2)除第一元素外其余元素均只有一个前驱,除最后元素外其余元素均只有一个后继
线性表:n个数据元素的有限序列
线性表之顺序表
概念:用一组地址连续的存储单元依次存储线性表的数据元素
特性:逻辑上相邻的数据元素,物理次序也是相邻的,是可以随机存取的储存结构,常用动态分配的一维数组表示线性表
下面是一个教师线性表```
#define maxsize 10 //定义教师最大数目
#define true 1 //对标志
#define false 0 //错标志
//教师信息的数据结构
typedef struct
{
int id ;//教师编号
char name[25];//教师姓名
}teacher;
//顺序表线性结构
typedef struct
{
teacher *elem;//基址
int length;//长度
}sqlist;
//定义sqlist类型变量
sqlist L;``
顺序表操作之初始化
Status InitList(SqList &L)
{
//构造一个空的顺序表L
L.elem = new ElemType[maxsize]; //分配内存空间
if(!L.elem) exit(-1);
L.length = 0;
return TRUE;
}
顺序表操作之取值
Status Get(SqList &L,int i,ElemType &e)
{
if(i<1||i>L.length) return ERROR;
e = L.elem[i-1];
return TRUE;
}
顺序表操作之查找
int Find(SqList L,ElemType e)
{
//查找值为e的数据元素,返回其序号
for(i=0;i<L.length;i++)
{
if(L.elem[i]==e) return i+1;
}
return FALSE; //查找失败
}
顺序表操作之插入
Status ListInsert(SqList &L,int i,ElemType e)
{
if((i<1)||(i>L.length+1)) return FALSE; //i不合法
if(L.length == maxsize) return FALSE; //满了
for(j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //将第n个至i个位置的元素后移
L.elem[i-1]=e; //将e放进第i个位置
}
顺序表操作之删除
Status ListDelete(SqList &L,int i)
{
//删除第i个元素,i的值为[1,L.length]
if((i<1)||(i>L.length)) return FALSE
for(j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j];
--L.length; //长度减一
return OK;
}
使用顺序表作为存储时,空间是一次性直接赋予的,故可能有空间不足或浪费空间的情况,那么为为了解决这种情况就出现了——链表。
概念:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的),包括数据域和指针域,数据域存数据,指针域指示其后继的信息。
单链表存储结构
typedef struct LNode
{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList;
单链表初始化
Status InitList(LinkList &L)
{
//构造一个单链表
L=new LNode; //生成头结点,用头指针L指向头结点
L->next =NULL;
return OK;
}
单链表取值
Status Get(LinkList L,int i,ElemType &e)
{
//在带头结点的单链表L中根据序号I获取元素的值,用e返回L中第i个数据元素的值
p=L->next;
j=1;//计数器
while(p&&j<i) //顺着链表向后扫描,直到j==i
{
p=p->next;
++j;
}
if(!p||j>i) return FALSE; //溢出
e=p->data; //找到该结点后获取该结点的数据域
return OK;
}
单链表查找
在这里插入代码片
LNode *Find(LinkList L,ElemType e)
{
p=L->next; //使p指向首元结点
while(p && p->data!=e)
{
p=p->next; //不符合条件就一直往下找
}
return p; //这里有两种情况,找到的时候返回指针p,如果找不到那么这个p则为null,因为最后一个指向的是null
}
单链表插入
Status ListInsert(LinkList &L,int i,ElemType e)
{
//在带头结点的单链表L中第i个位置插入值为e的新结点
p=L;j=0;
while(p&&(j<i-1))
{
p=p->next; //查找第i-1个结点,p指向该结点
++j;
}
if(!p||j>i-1) return FALSE;
s=new LNode; //生成一个新结点
s->data=e; //将结点*s的数据域置为e
s->next=p->next; //先接尾部
p->next=s; //再接头部
}
单链表删除
Status ListDelete(LinkList &L,int i)
{
//删除第i个元素
p=L;j=0;
while((p->next)&&(j<i-1))
{
p=p->next; //查找i-1个结点
++j;
}
if(!(p->next)||(j>i-1)) return FALSE; //当i>n或i<1时,不符合条件
q=p->next; //临时保存被删除的地址
p->next=q->next; //将前驱结点指向后驱
delete q; //释放删除结点的空间
return true;
}
头插法创建单链表
void CreateList(LinkList &L,int n)
{
//逆次序输出n个元素的值
L=new LNode;
L->next=NULL;
for(i=0;i<n;++i)
{
p=new LNode; //生成新结点
cin>>p->data; //输入新结点的数据域内容
p->next=L->next; //将新结点插到头结点之后
L->next=p;
}
}
尾插法创建单链表
void CreateList(LinkList &L,int n)
{
//正次序输入n个元素的值
L=new LNode;
L->next=NULL; //建立一个带头结点的空链表
r=L; //尾指针r指向头结点
for(i=0;i<n;++i)
{
p=new LNode; //生成新结点
cin>>p->data; //输入新结点的数据域内容
p->next=NULL;
r->next=p; //将新结点插入尾结点之后
r=p; //改变尾指针,使其指向新的尾结点
}
}
循环链表的内容可参考下面的博客
线性表的链式存储结构————循环链表(C语言完整程序)
ok,线性表的知识点就梳理到这里,这一章的内容是数据结构的入门基础,要把每一段代码都进行自己的理解(能默写出伪代码是最好的情况)所以等晚上我会再复习一遍这一篇内容,明天再复习一遍再开始整理下一篇栈和队列。打牢这一篇的基础对后面的学习大有裨益。