线性表(Linear List)
定义:由同类型数据元素构成的有序序列的线性结构。 引言:假设要表示一个一元多项式(见下图):
要表示这个多项式,需要先观察它的关键数据:
1.系数ai 2.指数i 3.多项式的项数n
表示方式:
1.顺序存储
这样的方式很方便,但是如果指数跨越很大比如:
这种情况下我们要去建立一个大小为101的数组,但是实际上我们只在这个数组的第一项和最后一项存储系数。这样的做法很浪费存储空间。
改进方法:
2.顺序存储结构中只表示非零项
首先定义一个顺序存储结构体
typedef int ElementType;
#define MAXSIZE 10
typedef struct LNode *List;//创建一个LNode类型的指针,同时定义别名为List
struct LNode{
ElementType Data[MAXSIZE];
int Last;//Last指向表尾
};
一些常见的操作及其实现
1.创建一个空表
List MakeEmpty(){
List Ptrl;
Ptrl=(List)malloc(sizeof (struct LNode));
Ptrl->Last=-1;
return Ptrl;
}
2.根据元素查找它在线性表中的位置
int Find(ElementType X,List Ptrl){
int i=0;
while(i<=Ptrl->Last && X!=Ptrl->Data[i]){
i++;
}
if(i>Ptrl->Last){//如果线性表中不存在X的值
return -1;
}
return i;//返回X在线性表中的存储位置
}
3.在表中指定位置插入一个元素
void insert(ElementType X,int i,List Ptrl){
int j;
if(IsFull(Ptrl)){//线性表满了则不执行
printf("表已经满了!!!");
return;
}
if(i<0 || i>Ptrl->Last+2){//线性表插入到头结点或者大于尾结点之后的两个结点
printf("插入位置不对!");
return;
}
for(j=Ptrl->Last;j>i;j--){
Ptrl->Data[j+1]=Ptrl->Data[j];//插入位置之后的地方依次往后移
}
Ptrl->Data[i]=X;
Ptrl->Last++;//插入了一个新的数,Last往后加1指向表尾
return;
}
4.判断表是否为空
int IsFull(List Ptrl){
if(Ptrl->Last==MAXSIZE-1){
return 1;
}
return 0;
}
5.删除指定位置元素
void delete(int i,List Ptrl){
int j;
if(i<1 || i>Ptrl->Last+1){//不存在这个位置
printf("不存在第%d个元素",i);
}
for(j=i;j<=Ptrl->Last;j++){
Ptrl->Data[j]=Ptrl->Data[j+1];
}
Ptrl->Last--;
return;
}
6.查询表的长度
int Length(List Ptrl){
return Ptrl->Last;//直接返回Last的值
}
除此之外,我们还可以采用另一种方法:
3.链表结构来存储非零项
首先定义链表的结点
typedef struct LNode *List;
typedef int ElementType;
struct LNode{
ElementType data;
List Next; //指针指向下一个线性表元素地址
};
一些常见的操作及其实现
1.创建一个空链表
List Create(){
List L;
L=(List) malloc(sizeof (struct LNode));
L->Next=NULL;
return L;
}
PS:
这里的L=(List) malloc(sizeof (struct LNode));它是指分配一个内存,大小是LNode的大小,并将这个内存地址转化为Link型,然后将赋给L,所以L为地址。是给L赋值,也就是L被改为指向malloc()新分配的地址,改变L的值,即i的地址。(假设L指向的是i的地址)。
如果这里写成 *L = (List)malloc(sizeof(struct LNode));是给L所指的变量赋值(假设L指向的是i的地址),也就是i值被改为malloc()新分配的地址,即改变i值。
2.查询表长度
int Length(List Ptrl){
List L=Ptrl;//创建一个新的变量L指向Ptrl第一个结点
int j=0;
while (L){//只要L没有到表尾就一直往后走然后记录表长
L=L->Next;
j++;
}
return j;
}
3.查询第K个位置的结点
List FindKth(int K,List Ptrl){
List L=Ptrl;
int i=1;
while (L!=NULL && i<K){
L=L->Next;
i++;
}
if(i==K) return L;
else return NULL;
}
4.查询X的值并返回此结点
List FindX(ElementType X,List Ptrl){
List L=Ptrl;
while (L->data!=X && L){
L=L->Next;
}
return L;
}
5.插入元素到表的第i个结点
List Insert(ElementType X,int i,List Ptrl){
List L1,L2;
if(i==1){//如果插入的结点位于表头
L1=(List)malloc(sizeof (struct LNode));
L1->data=X;
L1->Next=Ptrl;
return L1;
}
L1= FindKth(i-1,Ptrl);//先找到第i-1个位置的结点,因为我们要插入到第i个位置
if(L1== NULL){
printf("参数i错误");
return NULL;
} else{
L2=(List) malloc(sizeof (struct LNode));//申请结点
L2->data=X;
L2->Next=L1->Next;
L1->Next=L2;
return Ptrl;
}
}
PS:
L2->Next=L1->Next;
L1->Next=L2;
注意顺序,一定是先将新插入的结点先指向原来i-1指向的结点,再将i-1的结点指向新插入的结点。
6.删除表中第K个位置的结点
List DeleteKth(int K,List Ptrl){
List L,temp;
if(K==1){//查出来除了头结点之外只有一个结点
L=Ptrl;
if(Ptrl!=NULL) Ptrl=Ptrl->Next;
else return NULL;
free(L);
return Ptrl;
}
L= FindKth(K-1,Ptrl);
if(L==NULL){
printf("第%d个结点不存在",K-1);//K-1都没有查出来,那么肯定也没有K结点
}else if(L->Next==NULL){
printf("第%d个结点不存在",K);//查出来K-1,但是K不存在
}else{
temp=L->Next;
L->Next=temp->Next;
free(temp);
return Ptrl;
}
如果大家有好的想法,欢迎在评论区交流讨论... 原创不易,转载请标明出处