10.1 与408关联解析及本节内容介绍
链表比顺序表出现的顺序更加的频繁。
10.2线性表地顺序表示原理解析
线性表的特点:
(1)表中的元素的个数是有限的
(2)表中元素的数据类型相同。意味着每一个元素占用相同大小的空间。
(3)表中元素具有逻辑上的顺序性,在序列中的个元素排序有先后顺序。
线性表是逻辑存储结构。
使用数组(顺序存储)来实现的
数组:
可以随机存取(根据初始地址和元素序号)表中的任意一个元素
线性表的顺序表示简称顺序表
原来是7个元素,但是你是可以插入到第8个位置的。
意思就是数组第j个位置的数放到j+1个位置,第i-1个位置的放到第i个位置,
再在空出的i-1个位置处放入x。
删除操作:
把删除的元素赋值给e,保存下来。
空间没有被释放,因为数组一开始申请的时候已经定义好了。
另外一种实现顺序表的方法(动态分配)
不应去定义数组,而是去定义指针。
10.3顺序表的初始化及插入操作实战
因为是实战,全程手撸代码,是C++可执行文件
建议直接使用静态分配,动态空间容易出错(要用malloc申请空间),无非是一个在堆空间,一个是在栈空间。
驼峰命名法需要每个首字母大写
下面我将展示顺序表的插入实战代码及其解析:
#include <stdio.h>
#define MaxSize 50
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int length;//顺序表长度
}SqList;
//让顺序表存储其他类型元素时,可以快速完成代码修改,就是如果说改成char类型,通过别称只需要改动这一个就行
bool ListInsert(SqList &L,int i,ElemType element){ //判断 i 是否合法
if(1>i || i>L.length+1){ //判断插入的位置是否合法
return false;
}
//如果存储空间满了,不能插入
if(L.length>=MaxSize){ //超出空间了
return false;
}
//把后面的元素依次往后移动,空出位置,
for(int j=L.length;j>=i;j--){
L.data[j]=L.data[j-1];}//移动顺序表中的元素
L.data[i-1]=element; //放入要插入的元素
L.length++; //顺序表要加1
return true;
}
//打印函数输出
void PrintList(SqList L){
int i;
for(i=0;i<L.length;i++){
printf("%3d",L.data[i]); //为了打印到一行
}
printf("\n");
}
//主函数部分
int main() {
SqList L;//定义一个顺序表,变量L
bool ret;//ret用来装函数的返回值
L.data[0]=1; //放置元素
L.data[1]=2;
L.data[2]=3;
L.length=3; //设置长度
ret=ListInsert(L,2,60);//第一个是顺序表名L,第二个是要插入的位置,第三个是元素
if(ret){
printf("insert sqlist success\n");
PrintList(L);
}else{
printf("insert sqlist failure");
}
return 0;
}
结果展示:
10.4顺序表的删除及查询
因为结构体,我们删除的时候会改变数组的值和长度,所以要加上引用,
删除的元素需要带出来,所以要加上引用。
子函数一旦走到return就结束了
实参和形参的值可以不一样
bool ListDelete(SqList &L,int i,ElemType &e){ //判断 i 是否合法
if(1>i || i>L.length){ //判断删除的位置是否合法
return false;
}
//把后面的元素依次往后移动,空出位置,
e=L.data[i-1]; //获取顺序表中对应的元素,赋值给e
for(int j=i;j<L.length;j++){
L.data[j-1]=L.data[j];}//移动顺序表中的元素
L.length--; //顺序表要加1
return true;
}
int LocateElem(SqList L,ElemType e){
int i;
for(i=0;i<L.length;i++){
if(L.data[i]==e){
return i+1; }//i+1就是数组在顺序表中的位置
}
}
主函数如下:
int main() { SqList L;//定义一个顺序表,变量L int del; bool ret;//ret用来装函数的返回值 L.data[0]=1; //放置元素 L.data[1]=2; L.data[2]=3; L.length=3; //设置长度 ret=ListDelete(L,1,del);//第一个是顺序表名L,第二个是要插入的位置,第三个是元素 if(ret){ printf("delete succcess \n"); printf("deleted item value is %d\n",del); PrintList(L); }else{ printf("delete failure"); } ret=LocateElem(L,1); if(ret){ printf("find success\n"); printf("element position is %d\n",ret); }else{ printf("查找失败\n"); } return 0; }
10.5线性表的链式存储
顺序表是线性表的线性存储,由于线性表占用了一段连续的存储空间(造成了很多碎片),数组的大小也不好确定,插入和删除移动了大量元素。
数组申请了50个空间,只用了3个,造成大量碎片。
结构体里面用到了LNode,所以要事先声明结构体名称为LNode.
最后一个next指针域存储的是NULL
在a1前面还放了一个结点
头指针:链表中第一个结点的存储位置,用来标识单链表。
头节点:在单链表第一个结点之前附加的一个结点,为了操作上的方便。
(1)表头插入
(2)中间插入
p->next指向的是ai的位置赋给了q->next。
p->next=q
再把q指针赋给p->next
中间的先就可以去掉了
(3)表尾插入元素
q的指针域是空值
p的指针域位置指向q
接下来我们来看单链表删除操作
(1)表头删除元素
把q的指针位置就是a2赋给p的指针位置。
这就叫做断链。
(2)中间删除元素(表尾删除元素)跟前面差不多。
查找操作:
(1)按照序号查找
10.6OJ 作业说明
我们把输入,输出这样的一种组合,称为一个测试用例。