线性表

线性表定义以及基本操作

定义

  • 相同数据类型的n个数据元素组成的有限序列,n>=0
  • 除第一个元素以外,每个元素有且只有一个直接前驱
  • 除最后一个元素以外,每个元素有且只有一个直接后继
  • 线性表属于逻辑结构

基本操作

  • InitList ( &L ):初始化表,构造一个空的线性表
  • Length ( L ):返回线性表L的长度
  • LocateElem ( L , e ):按值查找
  • GetElem ( L , i ):按位查找
  • ListInsert( &L , i , e ):插入操作,在表L中第i个位置插入指定元素e
  • ListDelete( &L , i , e ):删除操作,删除表L中第i个位置的元素,并用e返回删除元素的值
  • PrintList( L ):输出操作,按照前后顺序输出线性表L中的元素
  • Empty( L ):判空操作,空为true,非空为false
  • DestroyLise( &L ):销毁操作。销毁线性表,并且释放空间

1 顺序表示

1.1 定义

  • 顺序存储又称为顺序表
  • 用一组地址连续的存储单元依次存储线性表中的数据元素
  • 逻辑上相邻的两个元素物理位置上也相邻
  • 逻辑顺序与物理顺序相同
  • 最主要特点是随机访问

1.2 基本操作的实现

  • 定义实现
    • 静态分配
#define MAXSIZE 1000
typedef struct
{
    ElemType data[MAXSIZE];
    int length;
}SqList;
  • 动态分配
#define MAXSIZE 1000
typedef struct
{
    ElemType *data;
    int MaxSize,length;
}SqList
//C的初始动态分配语句
L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);
//C++的初始动态分配语句
L.data=new ElemType[InitSize];
  • 插入操作 O(n)
bool ListInsert(SqList &L,int i,ElemType e)
{
    if(i<1||i>L.length+1) return false;//判定i的范围是否有效
    if(L.length>=MaxSize) return false;//判断当前L的长度是否达到最大长度
    for(int j=L.length-1;j>=i;j--)
    {
        L.data[j]=L.data[j-1];
    }
    L.data[i-1]=e;
    L.length++;
    return true;
}
  • 删除操作 O(n)
bool ListDelete(SqList &L,int i,ElemType &e)
{
    if(i<1||i>L.length) return false;
    e=L.data[i-1];
    for(int j=i;i<L.length;j++)
    {
        L.data[j-1]=L.data[j];
    }
    return true;
}
  • 按值查找 O(n)
    • 从前往后依次遍历即可

1.3 问题解决

  • 设将n(n>1)个整数存放到一维数组中,将R中保存的序列循环左移P个位置,即将R中的数据由(1 2 3 4 5 6…n)变为(3 4 5 6…n 1 2)
    • 算法思想:分成两段,分别颠倒,再将总序列颠倒
    • 1 2 3 4 5 6 -> 2 1 6 5 4 3 -> 3 4 5 6 1 2
void Reverse(int R[],int from,int to)
{
    int k;
    for(int i=0;i<(to-from+1)/2;i++)
    {
        k=R[from+i];
        R[from+i]=R[to-i];
        R[to-i]=k;
    }
}
void Converse(int R[],int n,int p)
{
    Reverse(R,0,p-1);
    Reverse(R,p,n-1);
    Reverse(R,0,n-1);
}
  • 给定一个长度为n一维数组,寻找出现次数最多的元素
    • 算法思想:利用map<int,int>存不同元素出现次数
int Search(int a[],int length)
{
    map<int,int>m;
    for(int i=0;i<length;i++)
    {
        ++m[a[i]];
    }
    int value=(m.begin())->first;
    int max=(m.begin())->second;
    for(map<int,int>::iterator iter=m.begin();iter!=m.end();iter++)
    {
        if(iter->second>max)
        {
            value=iter->first;
            max=iter->second;
        }
    }
    return value;
}

2 链式表示

2.1 单链表

  • 2.1.1 单链表定义

    • 通过一组任意的存储单元来存储线性表中的数据元素
typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;
  • 2.1.2 基本操作实现

    • 建立单链表
      • 头插法 O(n)
LinkList List_HeadInsert(LinkList &L)
{
    LNode *s;
    int k;
    L=(LinkList)malloc(sizeof(LNode));//创建头节点,并且分配内存
    L->next=NULL;
    cin>>k;
    while(k!=9999)//选择一个终止条件,这里用x=9999来代替
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=k;
        s->next=L->next;
        L->next=s;
        cin>>k;
    }
    return L;
}
  • 尾插法 O(n)
LinkList list_TailInsert(LinkList &L)
{
    LNode *s;
    LNode *r=L;
    int k;
    L=(LinkList)malloc(sizeof(LNode));//创建头节点,并且分配内存
    L->next=NULL;
    cin>>k;
    while(k!=9999)//选择一个终止条件
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=k;
        s->next=r->next;
        r->next=s;
        r=s;
        cin>>k;
    }
    return L;
}

  • 按位查找(查找的是节点)
LNode *GetELem(LinkList L,int i)
{
    int j=1;
    LNode *p=L->next;
    if(i==0)
        return L;
    if(i<1)
        return NULL;
    while(j<i&&p)
    {
        p=p->next;
        j++;
    }
    return p;
}
  • 按值查找(从头遍历,和上面差不多,方法定义的时候也是寻找节点)
  • 插入节点(随便想想啦,注意指针顺序)
  • 删除节点(同上)

2.2 双链表

  • 拥有两个指针,分别指向前驱节点和后驱节点
typedef struct DNode
{
    Elemtype data;
    struct Dnode *piror,*next;
}DNode.*Dlinklist;

2.3 循环链表

  • 循环单链表
    • 判空条件为:L->next==L
  • 循环双链表
    • 判空条件为:L->next == L && L->piror == L

2.4 静态链表

  • 借助数组来描述线性表的链式存储结构
#define MaxSize 100
typedef struct
{
    ElemType data; //保存数据
    int next;  //保存下一个节点的数组下标
}SLinkList[MaxSize];

+结束标志为:next==-1

顺序表与链表的比较

  • 总结一下大概就是顺序表存取方便,链表操作方便
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值