数据结构题目笔记-02-线性表及其实现 C语言

170 阅读4分钟

线性表(Linear List)

定义:由同类型数据元素构成的有序序列线性结构。 引言:假设要表示一个一元多项式(见下图):

x.png 要表示这个多项式,需要先观察它的关键数据: 1.系数ai 2.指数i 3.多项式的项数n

表示方式:

1.顺序存储

image.png 这样的方式很方便,但是如果指数跨越很大比如: image.png 这种情况下我们要去建立一个大小为101的数组,但是实际上我们只在这个数组的第一项和最后一项存储系数。这样的做法很浪费存储空间。

改进方法:

2.顺序存储结构中只表示非零项

image.png

首先定义一个顺序存储结构体

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;
    }

如果大家有好的想法,欢迎在评论区交流讨论...  原创不易,转载请标明出处