数据结构与算法——线性表

一、线性表及其顺序存储

ADT:
类型名称:线性表(List)
对象集:线性表是n个元素构成的有序序列
操作集:初始化,按值寻找,按序号寻找,插入,删除,求链表长

typedef struct LNode* List;
struct LNode
{
ElementType Data[MMAXSIZE];
int Last;
};
List Ptrl;代表整个线性表

#include<iostream>
using namespace std;
#define MaxSize 11
typedef struct LNode* List;
struct LNode
{
    int arr[MaxSize];
    int last;
};

List Ptrl;

//建立一个空表
List MakeEmpty()
{
    Ptrl = new struct LNode;
    Ptrl->last=-1;
    return Ptrl;
}

//插入
void Insert(int X,int i,List Ptrl)
{
    if(Ptrl->last==MaxSize-1)
    {
        cout << "表已满"<<endl;
        return;
    }
    if(i<1||i>Ptrl->last+2)
    {
       cout << "输入的位置不合法"<<endl;
       return;
    }
    for(int j=Ptrl->last;j>=i-1;j--)
    {
            Ptrl->arr[j+1]=Ptrl->arr[j];
    }
    Ptrl->arr[i-1]=X;//这个语句必须放后面,因为放前面会把插入的值移动到后面
    Ptrl->last++;
    return;
}

void Delete(int i,List Ptrl);
int Find(int X,List Ptrl);
int main()
{
    MakeEmpty();
    Insert(100,1,Ptrl);
    Insert(200,2,Ptrl);
    Insert(300,3,Ptrl);
    Insert(400,4,Ptrl);
    Insert(500,5,Ptrl);
    Insert(600,6,Ptrl);
    Insert(700,7,Ptrl);
    Insert(800,8,Ptrl);
    Insert(900,9,Ptrl);
    Insert(1000,10,Ptrl);
    Insert(23,2,Ptrl);//插入2号位置
    cout << Ptrl->arr[0]<<endl;
    cout << Ptrl->arr[1]<<endl;
    cout << Ptrl->arr[2]<<endl;
    cout << Ptrl->arr[3]<<endl;
    cout << Ptrl->arr[4]<<endl;
    cout << Ptrl->arr[5]<<endl;
    cout << Ptrl->arr[6]<<endl;
    cout << Ptrl->arr[7]<<endl;
    cout << Ptrl->arr[8]<<endl;
    cout << Ptrl->arr[9]<<endl;
    cout << Ptrl->arr[10]<<endl;
    Delete(2,Ptrl);//删除第二个位置的元素,200没了
    cout << Ptrl->arr[1]<<endl;//第一位应该不变仍然是100
    cout << Ptrl->arr[9]<<endl;//第9位应该是1000
    cout << Ptrl->arr[10]<<endl;//第十位应该位NULL即0

    cout << Find(1000,Ptrl) <<endl;//打印1000的位置应该是第9位,即换算成数组下标为10
}

//删除
void Delete(int i,List Ptrl)
{
    if(i<1||i>Ptrl->last+1)
    {
        cout << "输入的位置不合法"<<endl;
        return;
    }
    for(int j=i;j<=Ptrl->last;j++)
    {
        Ptrl->arr[j-1] = Ptrl->arr[j];
    }
    Ptrl->last--;
    Ptrl->arr[(Ptrl->last)+1] = 0;
    return;

}


//查找
int Find(int x,List Ptrl)
{
    int i=0;
    while(x!=Ptrl->arr[i]&&i<=Ptrl->last)
    i++;
    if(i<=Ptrl->last) return i;
    else return -1;
}

建立一个线性表并输出元素,在第二个位置插入23,此时共11个元素,打印结果正确,再删除第二个元素,那么23应该被删除,此时第2个元素又是200了,第9个元素应该是原来的1000,第十位没有元素。
代码结果:在这里插入图片描述
顺序存储在中间插入删除元素太麻烦,因为要移动很多元素

二、线性表的链式存储

无头指针!!!!

#include<iostream>
using namespace std;

typedef struct Node* List;
struct Node
{
    int data;
    List Next;
};

List Ptrl;

//初始化
List MakeList(List& Ptrl)
{
    int data;
    Ptrl = new struct Node;
    cin >> data;
    Ptrl->data = data;
    List Tail=Ptrl;
    for(int i=2;i<=10;i++)
    {
        cin >> data;
        List p = new struct Node;
        p->data = data;
        Tail->Next = p;
        p->Next=NULL;
        Tail = Tail->Next;
    }
    return Ptrl;
}


int Length(List Ptrl)
{
    int i=0;
    List p=Ptrl;
    while(p)
    {
       i++;
       p=p->Next ;
    }
    return i;
}


//按值寻找元素
List Find(int x,List Ptrl)
{

    while(x!=Ptrl->data&&Ptrl!=NULL)
        Ptrl = Ptrl->Next;
    if(Ptrl!=NULL) return Ptrl;
}

//按序号寻找元素
List Findth(int j,List Ptrl)
{
    List p=Ptrl;
    if(j>Length(p))
    {
        cout << "输入序号大于列表长度"<<endl;
    }
    else
    {
       for(int i=1;i<j;i++)
        {
            p = p->Next;
        }
        return p;
    }
}

//插入
                                                //S—>Next=P—Next;
                                                //P—>Next=S;
                                                //不能互换;否则地址成环路了
List Insert(int x,int i,List Ptrl)                                                //第一个if用于表头,因为表头比较特殊,前面没有相邻元素。                                                //第二个if用于检测是否插入线性表中,即前面有相邻元素才可以。
{
    if(i==1)
    {
        List s = new struct Node;
        s->Next = Ptrl;
        s->data = x;
        return s;//返回新表头指针
    }

    List p=Findth(i-1,Ptrl);
    if(p==NULL)
    {
        cout << "输入位置在链表之外"<<endl;
        return NULL;
    }else
    {
        List s = new struct Node;
        s->Next = p->Next;
        s->data = x;
        p->Next = s;
        return Ptrl;//返回表头指针
    }

}


//删除
List Delete(int i,List Ptrl)
{
    List temp;
    if(i==1)
    {
        List p = Ptrl;
        if(p!=NULL)
        {
            p = p->Next;
            return p;
        }
        else return NULL;
        free(p);
    }
    List s = Findth(i-1,Ptrl);
    if(s==NULL)
    {
        cout << "该结点压根不存在"<<endl;
    }else if(s->Next==NULL)
    {
        cout << "该结点不存在,但它的前一个结点存在"<<endl;
    }else
    {
        temp = s->Next;
        s->Next = temp->Next;
        free(temp);
        return Ptrl;
    }

}
int main()
{
    Ptrl = MakeList(Ptrl);
    //cout << Head->data<<endl;
    cout << Length(Ptrl)<<endl;//打印表长,应该为10
    cout << Findth(2,Ptrl)<<endl;//按序号查找元素地址
    Insert(100,3,Ptrl);
    cout << Ptrl->Next->data <<endl;
    cout << Ptrl<<endl;//这里是为了验证删除前后Ptrl仍然没变,仍然指向该链表头结点
    cout << Findth(2,Ptrl)<<endl;//返回2号元素的地址
    cout << Delete(2,Ptrl)<<endl;//返回删除后的链表
}

结果:在这里插入图片描述
链式存储方便在中间插入或删除元素,但是不方便在链尾删除元素,因为链尾删除元素时需要将尾指针设为NULL,但是不方便找尾结点地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值