线性表的练习题的博文链接~~戳这里
文章目录
PS:
关于->
和.
的区别
.
表示左边是实体,提取右边的成员。一般用于结构体
->
表示左边是指针,提取右边的成员
struct node{
int x;
};
struct node *a;
a是一个指向结点的指针。
我们要访问x的值,可以写*a.x
,也可以写a->x
顺序存储结构 P22
书上P22页,给出了线性表的动态分配顺序存储结构,如下
注意:这里写了一个ElemType
,这代表一个元素类型,使用的时候,你可以根据自己需要什么类型来改。
typedef struct{
ElemType *elem; //存储空间基址
int lenth; //当前线性表里面存放数据的长度
int listsize; //线性表的容量
}SqlList;
算法2.3 初始化一个顺序表 P23
基于线性表的顺序存储结构,我们写出顺序表的第一个算法,算法2.3,初始化一个顺序表
ps:我写的代码和书上略有出入,是因为书上的是C++伪代码,而我用的C语言实现,所以有些地方会有不同
比如函数形参你会看到书上SqList &L
这样写,这是C++里面的引用,而用C语言没有引用,所以改用指针代替,所以导致函数里面的写法也略有不同,这是语言的实现形式不一样,算法原理都一样,所以这些问题,就不再解释了。
/******
author: 1900
language: C
******/
#include<stdio.h>
#include<malloc.h>
#define List_Init_Size 100 //初始大小
#define List_Increase 10 //增量
typedef struct{
int *elem; //存储空间基址
int lenth; //当前线性表里面存放数据的长度
int listsize; //线性表的容量
}SqList;
int InitList_Sq(SqList *L){
L->elem=(int *)malloc(List_Init_Size*sizeof(int));
if(!L->elem){
return -1;//申请失败
}
L->lenth=0;
L->listsize=List_Init_Size;
return 1;
}
int main(){
SqList L; //声明一个顺序表
InitList_Sq(&L);//初始化
//将这个顺序表前十个空间,赋值为0-9,并且打印出来
for(int i=0;i<10;i++){
L.elem[i]=i;
L.lenth++;
printf("%d ",L.elem[i]);
}
}
算法2.4 顺序表插入元素 P24
下面这个例子:
创建了一个空的顺序表,初始空间为10,向其中插入了12个元素(所以用到了申请空间),最后遍历打印!
顺序表插入元素要注意几点:
1、在第i个位置插入元素,下标是i-1
2、所插入位置后边的所有元素都要后移一位
3、要先考虑,空间够不够插入这个元素,若不够,先申请空间
4、移动元素,我用了书上的方法,用双指针移动(其实可以用下标移动的,会简单的多,不过这里为了和书上一致用指针吧。。)
/*
author: 1900
language: C
*/
#include<stdio.h>
#include<malloc.h>
#define List_Init_Size 10 //初始大小
#define List_Increase 10 //增量
int cnt=0;
typedef struct{
int *elem; //存储空间基址
int lenth; //当前线性表里面存放数据的长度
int listsize; //线性表的容量
}SqList;
int InitList_Sq(SqList *L){
L->elem=(int *)malloc(List_Init_Size*sizeof(int));
if(!L->elem){
return -1;//申请失败
}
L->lenth=0;
L->listsize=List_Init_Size;
return 1;
}
//在第i个位置前插入元素e
int ListInsert_Sq(SqList *L,int i,int e){
if(i<1 || i>L->lenth+1) return -1; //位置不合法
if(L->lenth>=L->listsize){
int *newbase=(int *)realloc(L->elem,(L->listsize+List_Increase)*sizeof(int) );
if(!newbase) return -1;
L->elem=newbase;
L->listsize+=List_Increase;
}
//用两个指针,一个指向位置i-1,用来插入元素e
//另一个指向最后一个位置,用来移动元素
int *q=&(L->elem[i-1]);
for(int *p=&(L->elem[L->lenth-1]);p>=q;--p){
*(p+1)=*p;
}
*q=e; //插入元素e
++L->lenth;//表长+1
return 0;
}
int main(){
SqList L; //声明一个顺序表
InitList_Sq(&L);//初始化
//刚开始为空 一个一个插入 插入12个数
for(int i=1;i<=12;i++){
ListInsert_Sq(&L,i,i);
}
//遍历
for(int i=0;i<12;i++){
printf("%d ",L.elem[i]);
}
}
算法2.5 顺序表删除元素 P25
下面这个代码,创建了一个顺序线性表,为其前10个空间赋值为0-9,然后使用算法2.5删除了第3个元素,并打印了删除后的顺序表。
/******
author: 1900
language: C
******/
#include<stdio.h>
#include<malloc.h>
#define List_Init_Size 100 //初始大小
#define List_Increase 10 //增量
typedef struct{
int *elem; //存储空间基址
int lenth; //当前线性表里面存放数据的长度
int listsize; //线性表的容量
}SqList;
int InitList_Sq(SqList *L){
L->elem=(int *)malloc(List_Init_Size*sizeof(int));
if(!L->elem){
return -1;//申请失败
}
L->lenth=0;
L->listsize=List_Init_Size;
return 1;
}
//在顺序表L种删除第i个元素 并且用e返回其值
int ListDelete_Sq(SqList *L,int i,int *e){
if((i<1)||(i>L->lenth)) return -1; //i要合法
int *p=&(L->elem[i-1]); //指针p指向被删除元素地址
*e=*p;
int *q=&(L->elem[L->lenth-1]);//指针q指向被最后一个元素
for(++p;p<=q;++p){
*(p-1)=*p;//前移元素
}
--L->lenth;//表长减一
}
int main(){
SqList L; //声明一个顺序表
InitList_Sq(&L);//初始化
//将这个顺序表前十个空间,赋值为0-9,
for(int i=0;i<10;i++){
L.elem[i]=i;
printf("%d ",L.elem[i]);
L.lenth++;
}
printf("\n");
int e=0;
ListDelete_Sq(&L,3,&e);
printf("被删除的元素值为:%d\n",e);
printf("删除后的顺序表\n");
for(int i=0;i<9;i++){
printf("%d ",L.elem[i]);
}
}
算法2.6 顺序表中查找元素 P26
这个算法,你可能觉得我写的根书上的不一样。其实,书上是用了一个函数指针,书上的算法的作用是,在线性表中查找符合条件的元素,我写的是查找值等于e的元素,所以书上的查找更广义一些,他可以查等于,也可以查大于,等等。条件就写在compare
函数里,使用函数指针来传入函数。其他的原理都一样,掌握关键点就好。
//查找元素在线性表中的位序
int LocateElem_Sq(SqList *L,int e){
int i=1;
int *p=&(L->elem[0]);
while(i<=L->lenth&&(*p!=e)){
p++;
i++;
}
if(i<L->lenth) return i; //返回位序
else return 0;//没找到
}
算法2.7 顺序表的合并 P26
这个算法,注意不是简单的合并就行了,而是按照规则来合并,有点像归并排序的意思,但是比排序简单。
规则就是:给你两个非递减的顺序表,(所谓非递减,其实就是不严格的递增,就是带等于号的递增),要求你将其合并为一个顺序表,合并后的顺序表,仍然是非递减的。
我下面写的这个例子是:La顺序表:2 3 3 5 6 Lb顺序表:2 2 3 4 4 合并之后:合并后的Lc:2 2 2 3 3 3 4 4 5 6
/******
author: 1900
language: C
******/
#include<stdio.h>
#include<malloc.h>
#define List_Init_Size 100 //初始大小
#define List_Increase 10 //增量
typedef struct{
int *elem; //存储空间基址
int lenth; //当前线性表里面存放数据的长度
int listsize; //线性表的容量
}SqList;
int InitList_Sq(SqList *L){
L->elem=(int *)malloc(List_Init_Size*sizeof(int));
if(!L->elem){
return -1;//申请失败
}
L->lenth=0;
L->listsize=List_Init_Size;
return 1;
}
int MergeList_Sq(SqList *La,SqList *Lb,SqList *Lc){
int *pa=&(La->elem[0]); //指向头的指针
int *pb=&(Lb->elem[0]);
Lc->listsize=Lc->lenth=La->lenth+Lb->lenth;//初始化Lc
int *pc=Lc->elem=(int *)malloc(Lc->listsize*sizeof(int));//给Lc分配空间
if(*pc==NULL) return -1;//分配失败
int *pa_last=&(La->elem[La->lenth-1]); //指向尾的指针
int *pb_last=&(Lb->elem[Lb->lenth-1]);
while(pa<=pa_last &&pb<=pb_last){ //归并
if(*pa<=*pb){
*pc=*pa;pc++;pa++;
}
else{
*pc=*pb;pc++;pb++;
}
}
while(pa<=pa_last){ //插入La中剩余的
*pc=*pa;pc++;pa++;
}
while(pb<=pb_last){ //插入Lb中剩余的
*pc=*pb;pc++;pb++;
}
return 0;
}
int main(){
SqList La,Lb,Lc; //声明三个顺序表
InitList_Sq(&La);//初始化
InitList_Sq(&Lb);
//La:2 3 3 5 6
//Lb:2 2 3 4 4
La.elem[0]=2;La.elem[1]=3;La.elem[2]=3;
La.elem[3]=5;La.elem[4]=6;La.lenth=5;
Lb.elem[0]=2;Lb.elem[1]=2;Lb.elem[2]=3;
Lb.elem[3]=4;Lb.elem[4]=4;Lb.lenth=5;
MergeList_Sq(&La,&Lb,&Lc);
for(int i=0;i<10;i++)
printf("%d ",Lc.elem[i]);
}