ZJU数据结构(二)线性表

ZJU数据结构(二)线性表

1.什么是线性表

“线性表”:由同类型数据元素构成有序序列的线性结构

  1. 表中元素个数称为线性表的长度
  2. 线性表没有元素时,称为空表
  3. 表起始位置称为表头,表结束为止称为表尾

2.线性表的抽象数据类型描述

  1. 类型名称:线性表(List)
  2. 数据对象集:线性表是n(≥0)个元素构成的有序序列(a1,a2,…,an)
  3. 操作集:线性表L ∈ List,整数i表示位置,元素X∈ ElementTpye,线性表的基本操作有:
        1、 List MakeEmpty(): 初始化一个空线性表L;
        2、 ElementType FindKth(int K,List L): 根据位序K,返回相应元素;
        3、 int Find(ElementTpye X,List L) 在线性表L中查找X的第一次出现位置;
        4、 void Insert(ElementType X,int i,List L): 在位序i前插入一个新元素X;
        5、 void Delete(int i,List L): 删除指定位序i的元素;
        6、 int Length(List L): 返回线性表L的长度n。

3.线性表的顺序储存实现

利用数组的连续存储空间顺序存放线性表的个元素
注:顺序存储中i是序号的下标,从0开始

头文件命令及结构体格式
#include<stdio.h>
#define MAXSIZE 100 //MAXSIZE定义为Data数组的大小
typedef struct LNode*List;
struct LNode{
    ElementType Data[MAXSIZE];//ElementType 可以为任意类型
    int Last; //Last定义线性表的最后一个元素
};
struct LNode L;
List PtrL;
//访问下标为i的元素:L.Data[i]或者Ptrl->Data[i]
//线性表的长度:L.Last+1或者PtrL->Last+1
主要操作的实现:
  • 1.初始化(建立空的顺序表)
//初始化(建立空的顺序表)
List MakeEmpty()
{
    List L;
    L =(List)malloc(sizeof(struct LNode));
    L->Last=-1;
    return L;
}
  • 2.按值查找
//按值查找
int Find(ElementType X,List L)//ElementType 可以为任意类型
{
    int i=0;
    while(i<=L->Last&&L->Data[i]!=X)
        i++;
    if(i>L->Last)
        return -1;//如果没找到返回-1
    else
        return i;//如果找到了返回i下标
}
  • 3.插入操作实现
//插入操作实现
void Insert(ElementType X,int i,List L)//ElementType 可以为任意类型
{
    int j;
    if(L->Last==MAXSIZE-1)
    {
        printf("表满");//表假如空间已满,不能插入
        return;
    }
    if(i<1||i>L->Last+2)
    {
        printf("位置不合法");//位置越界
        return;
    }
    for(j=P->Last;j>=i-1;j--)
        L->Data[j+1]=L->Data[j]//从后往前挪一个,给a[i]腾出位置
    L->Data[i]=X; //新元素插入
    L->Last++; //Last仍然指向最后元素
    return;
}
  • 4.删除(删除表的第i(l<=i<=n)个位置上的元素)
//删除(删除表的第i(l<=i<=n)个位置上的元素)
void Delete(int i,List L)
{
    int j;
    if(i<1||i>L->Last+1)
    {
        printf("L->Data[%d]不存在元素",i);//位置越界
        return;
    }
    for (j=i,j<=L->Last;j++) //从前往后依次向前挪一个,将a[i]覆盖了
        L->Data[j-1]=L->Data[j];
    L->Last--;
    return;// Last仍然指向最后元素
}
  • 5.按序查找
//按序查找
ElementType FindKth(int K,List L)
{
    if(K<0||L->Last<K)//位置越界
    {
        printf("L->Data[%d]不存在元素",K);
        return;
    }
    return L->Data[K];
}
  • 6.求表长
//求表长
int Length(List L)
{
    return L->Last-1;
}
  • 测试代码段
//test
int main(){
    int i=0;
    L=MakeEmpty();//
    Insert(22,0,L);
    printf("在线性表L-Data[0]插入22\n");
    Insert(33,0,L);
    printf("在线性表L-Data[0]插入33\n");
    Insert(44,0,L);
    printf("在线性表L-Data[0]插入44\n");
    Insert(55,0,L);
    printf("在线性表L-Data[0]插入55\n");
    printf("此时的线性表为:");
    for(i=0;i<Length(L);i++)
        printf("%d ",L->Data[i]);
    printf("\n");
    printf("查找值为22的下标是:%d\n",Find(22,L));
    printf("下标为2的线性表的值是:%d\n",FindKth(2,L));
    Delete(2,L);
    printf("删除线性表中下标为2的元素\n");
    Delete(2,L);
    printf("删除线性表中下标为2的元素\n");
    printf("此时的线性表为:");
    for(i=0;i<Length(L);i++)
        printf("%d ",L->Data[i]);
    printf("\n");
    return 0;
}

4.线性表的链式存储实现

不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系。

  • 插入、删除不需要移动数据元素,只需要修改“链”。
头文件命令及结构体格式
#include<stdio.h>
#include<malloc.h>
typedef struct ElementType;//ElementType可以定义为任意类型
typedef struct LNode*List;
struct LNode
{
    ElementType Data;
    List Next;
};
struct Lnode L;
List L;
主要操作的实现:
  • 1.初始化链表
//初始化链表
List MakeEmpty()
{
    List L=(List)malloc(sizeof(struct LNode));
    L=NULL;
    return L;
}
  • 2.以遍历链表的方法求链表长度
//以遍历链表的方法求链表长度
int Length(List L)
{
    List p=L;//p指向表的第一个节点
    int j=0;
    while(p) //当p不为空
    {
        p=p->next;
        j++;//p指向表的第j个节点
    }
    return j;
}
  • 3.按序号查找
//按序号查找
List FindKth(int K,List L)
{
    List p=L;
    int i=1; //从1开始
    while(p!=NULL&&i<K)
    {
        p=p->Next;
        i++
    }
    if(i==K)
        return p;//找到第K个,返回指针
    else return NULL;//否则返回空值
}
  • 4.按值查找
//按值查找
List Find(ElementType X,List L)
{
    List p=L;
    while(p!=NULL&&p->Data!=X)
        p=p->Next;
    return p;
}
  • 5.插入
        1.先构造一个新的结点,用s指向;
        2.在找到链表的第i-1个结点,用p指向;
        3.然后修改指针,插入节点(p之后插入的新结点是s)
             s->Next =p->Next, p->Next=s
//插入
List Insert(ElementType X,int i,List L)
{
    List p,s;
    if(i==1)//新结点插入在表头
    {
        s=(List)malloc(sizeof(struct LNode));
        s->Data=X;
        s->Next=L;
        return s;
    }
    p=FindKth(i-1, L);//查找第i-1个结点
    if(p==NULL)//第i-1个结点不存在
    {
        printf("结点错误");
        return NULL;
    }
    else
    {
        s=(List)malloc(sizeof(struct LNode));
        s->Data=X;
        s->Next=p->Next;    //将s的下一个结点指向p的下一个结点
        p->Next=s;          //将p的下一结点改为s
        return L;
    }
}
  • 6.删除
        1.先找到链表的第i-1个结点,用p指向;
        2.再用指针s指向要被删除的结点(p的下一个结点);s=p->Next
        3.然后修改指针,删除s所指结点;p->Next=s->Next
        4.最后释放s所指结点 free(s)
//删除
List Delete(int i,List L)
{
    List p,s;
    if(i==1) //若删除第一个结点
    {
        s=L;//s指向第一个结点
        if(L!=NULL)//从链表中删除
            L=L->Next;
        else
            return NULL;
        free(s);
        return L;
    }
    p=FindKth(i-1,L);//查找第i-1个结点
    if(p==NULL||p->Next==NULL)
    {
        printf("结点不存在")
        return NULL;
    }
    else
    {
        s=p->Next//s指向第i个结点
        p->Next=s->Next;
        free(s);
        return L;
    }
}
  • 7.输出链表元素
//输出链表元素
void Print(List L)
{
    List t;
    int flag=1;
    printf("当前链表为:");
    for(t=L;t;t->Next)
    {
        printf("%d",t->Data);
        flag=0;
    }
    if(flag)
        printf("NULL");
    printf("\n");
}


//8.测试
int main()
{
    L=MakeEmpty();
    Print(L);
    L=Insert(22, 1, L);
    L=Insert(33, 1, L);
    L=Insert(44, 1, L);
    L=Insert(55, 1, L);
    Print(L);
    printf("当前情况链表长度为:%d\n"length(L));
    printf("此时链表中第三个结点的值为:%d\n",FindKth(3,L)->Data);
    printf("查找22是否在该链表中:");
    if(Find(22,L))
        printf("Yes \n");
    else
        printf("No  \n");
    printf("查找33时都在该链表中:")if(Find(33,L))
        printf("Yes \n");
    else
        printf("No  \n");
    L=Delete(1,L);
    L=Delete(4,L);
    Print("删除后\n");
    Print(L);
    return 0;
}

课后编程练习链接

        1. 两个有序链表序列的合并 这是一道C语言函数填空题,训练最基本的链表操作。一定要做;

        2. 一元多项式的乘法与加法运算 在“小白专场”里,我们会详细讨论C语言实现的方法。本题一定要做;

        3. Reversing Linked List 根据某大公司笔试题改编的2014年春季PAT真题,不难,可以尝试;

        4. Pop Sequence Pop Sequence 是2013年PAT春季考试真题,考察队堆栈的基本概念的掌握,应可以一试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值