数据结构概述1 线性表

这篇博客详细介绍了数据结构中的线性表,包括顺序存储和链式存储两种方式。在顺序存储中,讨论了初始化、插入、删除和查找操作,并提供了C语言实现。对于链式存储,不仅涵盖了不带头节点和带头节点的单链表操作,还涉及了双向链表的插入和删除。此外,文章提到了数据逻辑结构的四种基本类型和数据物理结构的四种形式,以及算法的五个基本特征。
摘要由CSDN通过智能技术生成

目录

数据逻辑结构

数据的物理结构

算法的五个特征

时间复杂度

空间复杂度

线性表

顺序存储的线性表

 顺序表结构

初始化表

插入操作

删除操作

按值查找位置

按位置取值

将两个从小到大排序的顺序表,归并成一个

链式存储的线性表(不带头节点)

链表结构

头插入法建立单链表

尾插入法建立单链表

求单链表的表长(长度不是从0开始算)

链式存储的线性表(带头节点)

初始化

尾插入法建立单链表

插入操作

删除操作

求单链表的表长(长度不是从0开始)

按位查找

按值查找

双向链表

链表结构

插入操作

删除操作


数据逻辑结构

1.集合结构

2.线性结构

3.树形结构

4.图形结构

数据的物理结构

1.顺序结构

2.链式结构

3.索引结构

4.散列结构

算法的五个特征

1.有穷性

2.确定性

3.有效性

4.有0个或多个输入

5.有1个或多个输出

时间复杂度

算法中执行次数最多的那条语句的执行次数,通常是最内层循环的循环体。

空间复杂度

执行算法所需要的存储空间

线性表

顺序存储的线性表

 顺序表结构

#define INIT_SIZE 100 //线性表存储空间的 初始分配量
#define INCREMENT 10 // 线性表存储空间的 分配增量
typedef int ElemType; // 定义元素类型为int 
typedef struct
{ 
    ElemType *elem; // 存储空间的基地址 
    int length; // 当前长度
    int listsize; //当前分配的存储容量(以 sizeof(ElemType)为单位)
}SqList;

初始化表

int InitList_Sq(SqList *L)//初始化顺序表,成功返回1,失败返回0
{ 
    L->elem=(ElemType *)malloc(INIT_SIZE*sizeof(ElemType));
    if(!L->elem) return 0; //初始化失败
    L->length=0;
    L->listsize=INIT_SIZE;
    return 1; //初始化成功
}

插入操作

//在顺序表L的第i个位置之前插入新的元素e,若插入成功则返回1,否则返回0
int ListInsert_Sq(SqList *L,int i,ElemType e)
{ 
    int j;
    ElemType *newbase;
    if(i<0 || i>L->length) 
        return 0; //插入位置不合法,插入失败
    if(L->length>=L->listsize) //当前存储空间已满,增加分配空间
    { 
        newbase=(ElemType *)realloc(L->elem,(L->listsize+INCREMENT)*sizeof(ElemType));
        if(!newbase) return 0; //存储分配失败,插入失败
        L->elem = newbase;
        L->listsize += INCREMENT;
    }
    for(j=L->length-1;j>=i;j--)
    {
        L->elem[j+1] = L->elem[j]; //插入位置及之后的元素从后开始向后移动
    }
    L->elem[i]=e; //插入e
    ++L->length; //表长增1
    return 1; //插入成功
}

删除操作

int ListDelete_Sq(SqList *L,int i,ElemType *e)
{ 
    int j;
    if(i<0 || i>L->length-1) return 0
    *e=L->elem[i]; //将被删除元素的值赋给e
    for(j=i+1; j<=L->length-1; j++)
    {
        L->elem[j-1]=L->elem[j]; --L->length;
    }
    return 1; //删除成功
}

按值查找位置

//在顺序线性表L中查找第1个值与e相等的元素的位序,若找到,则返回其在L中的位序,否则返回-1
int LocateElem_Sq(SqList L, ElemType e)
{ 
    int i=0; //i的初值为最前面一个元素的位序
    while(i<L.length&&L.elem[i]!=e) //从前向后逐一比较
        i++;
    if(L.elem[i]==e) //查找成功,i为与e相等的第一个元素的位序
        return i;
    else 
        return -1; //查找失败
}

按位置取值

//在顺序线性表L中取第i个元素存入e中,若成功,则返回1,否则返回0
int Get_SqList(SqList L,int i,ElemType *e)
{  
    if(i<0||i>L.length-1) 
        return 0;//没有第i个元素,读取失败
   *e=L.elem[i];
    return 1; //读取成功
}

将两个从小到大排序的顺序表,归并成一个

//已知顺序线性表LA和LB的元素按值非递减排列,归并LA和LB得到新的顺序线性表LC,LC的元素也按值非递减排列,成功返回1,失败返回0
int MergeList_Sq(SqList LA, SqList LB, SqList* LC)
{ 
    int i=0,j=0,k=0;
    LC->listsize = LA.length + LB.length;//拿到LC的长度
    LC->elem=(ElemType*)malloc(LC->listsize*sizeof(ElemType));//给LC分配空间
    if(!LC->elem) return 0;
    while(i<LA.length&&j<LB.length)
    {
        if(LA.elem[i]<=LB.elem[j])
            LC->elem[k++] =LA.elem[i++];
        else 
            LC->elem[k++]=LB.elem[j++];
    }
    while(i<LA.length) LC->elem[k++]=LA.elem[i++];
    while(j<LB.length) LC->elem[k++]=LB.elem[j++];
    LC->length=k;
    return 1;
}

链式存储的线性表(不带头节点)

链表结构

//建立链表结点
typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

头插入法建立单链表

//建立一个单链表L,输入n个元素的值
LinkList CreatHead_LinkList(int n)
{ 
    LinkList L=NULL;//建立空链表L
    LNode *s;
  int i;
    for(i=0; i<=n-1; i++)
    { 
        s=(LNode *)malloc(sizeof(LNode));//生成新节点
        printf("请输入第%d个元素的值:",i);
        scanf("%d",&s->data);//输入元素值
    s->next=L; 
    L=s;
    }
    return L;
}

尾插入法建立单链表

//建立一个单链表L,输入n个元素的值
LinkList CreatRear_LinkList(int n)
{ 
    LinkList L=NULL;//定义一个空表
    LNode *s,*r=NULL;//定义新节点指针和尾指针
    int i;   
    for(i=0; i<=n-1; i++)
    { 
        s=(LNode *)malloc(sizeof(LNode));//生成新节点
        printf("请输入第%d个元素的值:",i);
        scanf("%d",&s>data); //输入元素值
        if(L==NULL) //插入的节点是最前面的节点
            L=s;
    else //插入的节点是第一个以外的节点 
            r->next=s;   
        r=s; //r恒指向插入后的链表尾节点
    }  
    if(r!=NULL)//如果链表非空,则尾节点的指针域置为空  
        r->next=NULL
    return L;
}

求单链表的表长(长度不是从0开始算)

//当链表不带头节点时
int Length_LinkList2(LinkList L)
{ 
    LNode *p=L;   
    int i; //设计数器变量i
    if(p==NULL) return 0; //为空表返回0   
    i=1; //为非空表,p指向最前面的节点
    while(p->next)   
    { p=p->next;i++; }   
    return i;
}

链式存储的线性表(带头节点)

初始化

//构建一个带头节点的空链表,用L返回其头指针,若失败则返回0
LinkList Init_LinkList(LinkList L)
{ 
    L=(LNode *)malloc(sizeof(LNode));//分配一个头节点
    if(!L) return 0; //分配失败
    L->next = NULL; //头节点的指针域为空
    return L;
}

尾插入法建立单链表

//建立带头节点的单链表L,输入n个元素的值
LinkList Create_LinkList (int n)
{ 
    LNode *L,*p,*q;
    int i;

    //先建立一个带头节点的单链表
    L=(LNode *)malloc(sizeof(LNode));
    L->next=NULL;

    q=L; //q的初始值指向头节点
    for(i=0; i<=n-1; i++)
    { 
        p=(LNode *)malloc(sizeof(LNode));    /*生成新节点*/ 
        printf("请输入第%d个元素的值:",i);   
        scanf("%d",&p->data);//输入元素值
        p->next=NULL;q->next=p;q=p;//将该节点插入到表尾
    }
    return L;
}

插入操作

//在带头节点的单链表L中第i个位置之前插入元素e,若插入成功则返回1,否则返回0
int Insert_LinkList (LinkList L, inti,ElemType e)
{ 
    LNode *p,*s;
    int j;
    p=L; j=-1;
    while(p&&j<i-1) 
    {p=p->next;j++;}//寻找第i-1个节点
    if(!p || j>i-1) 
        return0; //i值不合法
    s=(LNode *)malloc(sizeof(LNode));//生成新节点
    s->data=e;
    s->next=p->next; p->next=s;//实现插入
    return 1;
}

删除操作

//在带头节点的单链表L中,删除第i个元素,并由e返回其值,若删除成功,则返回1,否则返回0
int Delete_LinkList (LinkList L, inti,ElemType *e)
{     
    LNode *p,*q;
    int j;
    p=L; j=-1;
    //寻找第i个节点,并令p指向其前驱
    while(p->next &&j<i-1) 
    { p=p->next; j++; }

    //删除位置不合理
    if(!(p->next)||j>i-1) 
        return 0; 
    q=p->next;
    *e=q->data; //用e返回被删节点数据域的值
    p->next=q->next; 
    free(q); //删除并释放节点
    return 1;
}

求单链表的表长(长度不是从0开始)

int Length_LinkList1(LinkList L)//当链表带头节点时
{ 
    LNode *p=L;//p指向头节点
    int i=0;//设计数器变量i
    while(p->next) //p指针依次后移
    { p=p->next; i++; }
    return i;
}

按位查找

//在带头节点的单链表L中查找第i个元素,若成功则返回该节点,否则返回空
LNode *Get_LinkList(LinkList L,int i)
{ 
    LNode *p=L; //p指向单链表L的头节点   
    int j=-1;   
    while(p->next!=NULL&&j<i)   
    { 
        p=p->next;
        j++; 
    }   
    if(j==i) return p;   
    else return NULL;
}

按值查找

//在带头节点的单链表L中查找与给定值相同的元素的位序,若成功则返回该节点,否则返回-1
int Locate_LinkList(LinkList L,ElemType e)
{ 
    LNode *p=L->next; //p指向单链表L的最前面的节点
    int i=0;
    while(p!=NULL&&p->data!=e)
    { 
        p=p->next;i++; 
    }
    if(p->data==e) 
        return i;
    else 
        return -1;
}

双向链表

链表结构

typedef struct DuLNode{
    ElemType data;
    struct DuLNode *prior;
    struct DuLNode *next;
}DuLNode,*DuLinkList;

插入操作

//设L为双向循环链表的节点,在地址为p的节点之后插入地址为s的新节点
void inselem(DuLinkList L,ElemType e,DuLNode p)
{ 
    DuLNode s,r;  
    s=(DuLNode)malloc(sizeof(DuLNode));  
    s->data=e; //建立一个新节点s
    r=p->next;  
    s->next=r;   
    r->prior=s; //插在节点p之后
    p->next=s;
    s->prior=p;
}

删除操作

//设L为双向循环链表的头节点,删除地址为p的节点
void delelm(DuLinkList L, DuLNode p)
{ 
    DuLNode q,r;   
    q=p->prior;   
    r=p->next;   
    q->next=r;   
    r->prior=q;   
    free(p);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yao2424022071

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值