考纲要求:在算法实现方面要求,能够根据实际问题的需求来决定采用何种存储结构并给出具体的算法,如:插入、删除满足条件的链表节点,在链表上排序等。
1,线性表的顺序表示和实现
1.1 初始化
1. 初始化线性表 L(参数用引用)
Status InitList_Sq(SqList &L){
//构造一个空的顺序表 L
L.elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(!L.elem) exit(OVERFLOW); //存储分配失败
L.length=0; //空表长度为 0
return OK;
}
2.初始化线性表 L (参数用指针)
Status InitList_Sq(SqList *L){ //构造一个空的顺序表 L
L-> elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(! L-> elem)
exit(OVERFLOW); //存储分配失败
L-> length=0; //空表长度为 0
return OK;
}
1.2 取值
1.取值(根据位置 i 获取相应位置数据元素的内容) 获取线性表 L 中的某个数据元素的内容
int GetElem(SqList L,int i,ElemType &e) {
if (i>L.length) return ERROR; //判断 i 值是否合理,若不合理,返回 ERROR
e=L.elem[i-1]; //第 i-1 的单元存储着第 i 个数据
return OK;
}
可以看出顺序表的读取是随机存储的。
1.3 查找
在线性表 L 中查找值为 e 的数据元素
int LocateELem(SqList L,ElemType e) {
for (i=0;i< L.length;i++)
if (L.elem[i]==e) return i+1;
return 0;
}
1.4 插入
插入(插在第 i 个结点之前)
【算法步骤】
(1)判断插入位置 i 是否合法。
(2)判断顺序表的存储空间是否已满。
(3)将第 n 至第 i 位的元素依次向后移动一个位置,空出第 i 个位置。
(4)将要插入的新元素 e 放入第 i 个位置。
(5)表长加 1,插入成功返回 OK。
在线性表 L 中第 i 个数据元素之前插入数据元素 e
Status ListInsert_Sq(SqList &L,int i ,ElemType e){
if(i>L.length+1) return ERROR; //i 值不合法
if(L.length==MAXSIZE) return ERROR; //当前存储空间已满
for(j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //插入位置及之后的元素后移
L.elem[i-1]=e; //将新元素 e 放入第 i 个位置
++L.length; //表长增 1
return OK;
}
1.5 删除
将线性表 L 中第 i 个数据元素删除
Status ListDelete_Sq(SqList &L,int i){
if((i>L.length)) return ERROR; //i 值不合法
for (j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //被删除元素之后的元素前移
--L.length; //表长减 1
return OK;
}
2.线性表的链式表示和实现
2.1 单链表的基本操作与实现
2.1.1,初始化
初始化(构造一个空表 )
【算法步骤】
(1)生成新结点作头结点
(2)用头指针 L 指向头结点
(3)头结点的指针域置空
【算法描述】
Status InitList_L(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
补充1:清空 // 将 L 重置为空表
Status ClearList(LinkList &L){
LinkList p,q;
p=L->next; //p 指向第一个结点
while(p)
{
q=p->next; delete p; p=q;
}
L->next=NULL; //头结点指针域为空
return OK;
}
补充2:求表长
intListLength_L(LinkList L){
//返回 L 中数据元素个数
LinkList p;
p=L->next;
i=0;
while(p){
i++;
p=p->next;
}
return i;
}
2.1.2,取值 (根据位置 i 获取相应位置数据元素的内容)
//获取线性表 L 中的某个数据元素的内容
Status GetElem_L(LinkList L,int i,ElemType &e){
p=L->next; j=1; //初始化
while(p&&j<i){ //向后扫描,直到 p 指向第 i 个元素或 p 为空
p=p->next; ++j;
}
if(!p || j>i)return ERROR; //第 i 个元素不存在
e=p->data; //取第 i 个元素
return OK;
}//GetElem_L
2.1.3,查找 (根据指定数据获取数据所在的位置)
//在线性表 L 中查找值为 e 的数据元素
LNode *LocateELem_L (LinkList L,Elemtype e) {
//返回 L 中值为 e 的数据元素的地址,查找失败返回 NULL
p=L->next;
while(p &&p->data!=e)
p=p->next;
return p;
}
2.1.4,插入 (插在第 i 个结点之前)
Status ListInsert_L(LinkList &L,int i,ElemType e){
p=L;j=0;
while(p&&j<i−1){
p=p->next;++j;
} //寻找第 i−1 个结点
if(!p||j>i−1)return ERROR; //i 大于表长+ 1 或者小于 1
s=new LNode; //生成新结点 s
s->data=e; //将结点 s 的数据域置为 e
s->next=p->next; //将结点 s 插入 L 中
p->next=s;
return OK;
}//ListInsert_L
单链表的建立(前插法)
void CreateList_F(LinkList &L,int n){
L=new LNode;
L->next=NULL; //先建立一个带头结点的单链表
for(i=n;i>0;--i){
p=new LNode; //生成新结点
cin>>p->data; //输入元素值 cin>>键盘输入并将值给数据域
p->next=L->next;
L->next=p; //插入到表头
}
}//CreateList_F
头插法另外一种比较好理解的算法形式
void CreateListF(LinkList *&L,ElemType a[ ],int n)
{ LinkList *s; int i;
L=(LinkList *)malloc(sizeof(LinkList)); //创建头节点
L->next=NULL; //头节点的next域置为NULL
for (i=0;i<n;i++)
{ s=(LinkList *)malloc(sizeof(LinkList));//创建新节点
s->data=a[i];
s->next=L->next; //将*s插在首节点之前,头节点之后
L->next=s;
}
}
单链表的建立(尾插法)
void CreateList_L(LinkList &L,int n){
//正位序输入 n 个元素的值,建立带表头结点的单链表 L
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; //r 指向新的尾结点
}
}//CreateList_L
2.1.5,删除 (删除第 i 个结点)
步骤 (1)找到 ai-1 存储位置 p
(2)临时保存结点 ai的地址在 q 中,以备释放
(3)令 p->next 指向 ai的直接后继结点
(4)将 ai的值保留在 e 中
(5)释放 ai的空间
//将线性表 L 中第 i 个数据元素删除
Status ListDelete_L(LinkList &L,int i,ElemType &e){
p=L;j=0;
while(p->next &&j<i-1){//寻找第 i 个结点,并令 p 指向其前驱
p=p->next; ++j;
}
if(!(p->next)||j>i-1) return ERROR; //删除位置不合理
q=p->next; //临时保存被删结点的地址以备释放
p->next=q->next; //改变删除结点前驱结点的指针域
e=q->data; //保存删除结点的数据域
delete q; //释放删除结点的空间
return OK;
} //ListDelete_L
3. 有序链表的合并
—将这两个有序链表合并成一个有序的单链表。
—要求结果链表仍使用原来两个链表的存储空间,不另外占用其它的存储空间。
—表中允许有重复的数据。
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
pa=La->next;
pb=Lb->next;
pc=Lc=La; //用 La 的头结点作为 Lc 的头结点
while(pa && pb){
if(pa->data<=pb->data){
pc->next=pa;pc=pa;pa=pa->next;
}
else{
pc->next=pb; pc=pb; pb=pb->next;
}
}
pc->next=pa?pa:pb; //插入剩余段
delete Lb; //释放 Lb 的头结点
}
4. 和结构体结合
图书信息管理系统,如何管理数据和组织数据
图书顺序表和链表表示
//图书顺序表
struct Book {
char ISBN[20];//ISBN
char name[50];//书名
int price;//定价
};
typedef struct
{//顺序表
Book *elem;
int length;
} SqList;
//图书链表
struct Book {
char ISBN[20];//ISBN
char name[50];//书名
int price;//定价
};
typedef struct LNode
{//链表
Book data;
struct LNode *next;
}LNode,*LinkList;