其他分享
首页 > 其他分享> > 2021-1-23数据结构总结(1)

2021-1-23数据结构总结(1)

作者:互联网

线性表包含顺序表(顺序存储)和链表(链式存储)

 

1、静态分配的顺序表实现

​#include<stdio.h>
#define MaxSize 10    //定义最大长度
typedef struct{
    int data[MaxSize];    //静态数组存放数据元素
    int length;    //定义当前长度
}SqList;


//基本操作--初始化一个顺序表
void InitList(Sqlist &L){
    for(int i=0; i<MaxSize; i++)
        L.data[i]=0;    //将所有数据元素设置为默认初始值
    L.length=0;    //初始长度为0
}


//基本操作--向顺序表插入新元素
bool ListInsert(SqList &L, int i; int e){
    if(i<1||i>L.length+1)   //判断i的范围是否有效,顺序表下标从1开始,但是数组下标从0开始
        return false;
    if(L.length>=MaxSize)   //  当前存储空间已满,不能插入
        return false;
    for(int j=L.length; j>=i; j--)  //将第i个及之后的元素向后移
        L.data[j]=L.data[j-1];
    L.data[i-1]=e;  //第i个位置放入e
    L.length++:
    return ture;
}
//时间复杂度:最好、最坏、平均 ==== O(1)、O(n)、O(n)


//基本操作--向顺序表删除新元素
bool ListDelect(SqList &L, int i; int &e){  //删除的值e需要返回,加上取地址符&
    if(i<1||i>L.length+1)   //判断i的范围是否有效,顺序表下标从1开始,但是数组下标从0开始
        return false;
    e=L.data[i-1];  //将被删除的值赋值给e
    for(int j=i; j<L.length; j++)   //将第i个位置后的元素前移
        L.data[j-1]=L.data[j];  //顺序表下标从1开始,但是数组下标从0开始
    L.length--;
    return ture;
}
//时间复杂度:最好、最坏、平均 ==== O(1)、O(n)、O(n)


int main(){
    SqList L;    //声明一个顺序表
    InitList(L);    //初始化顺序表
    //.........
    for(int i=0; i<L.length; i++)    //访问并打印顺序表各个元素
        printf("data[%d]=%d\n", i, L.data[i]);
    ListInsert(L,3,3);
    int e=-1;
    if(ListDelect(L, 3, e))
        printf("已删除第3个元素,删除元素值为=%d\n",e);
    else
        printf("位序i不合法,删除失败\n");
    return 0;
}

 

2、动态分配的顺序表实现

#include<stdlib.h>    //malloc、free函数的头文件

#define InitSize 10    //默认最大长度
typedef struct{
    int *data;    //指示动态分配数组的指针
    int MaxSize;    //顺序表的最大容量
    int length;    //定义当前长度
}SqList;


//基本操作--初始化一个动态分配的顺序表
void InitList(Seqlist &L){
    //用malloc函数申请一片连续的存储空间
    L.data=(int *)malloc(InitSize*sizeof(int));
    L.length=0;
    L.MaxSize=InitSize;
}


//基本操作--增加动态数组的长度
void IncreaseSize(SeqList &L,int len){
    int *p=L.data;  //重新定义一个指针,指向原数据
    L.data=(int *)malloc((L.MaxSize+len)*sizeof(int));     //重新申请一片增加长度的顺序表
    for(int i=0; i<L.length; i++){  //将原本的数据复制到新区域
        L.data[i]=p[i];
    }
    L.MaxSize=L.MaxSize+len;
    free(p);    //释放原来的内存空间
}


//基本操作--顺序表的按位查找
ElemType GetElem(SeqList L, int i){
    return L.data[i-1];
}


//基本操作--顺序表的按值查找
int LocateElem(SeqList L, ElemType e){
    for(int i=0; i<L.length; i++)
        if(L.data==e)
            return i+1;     //下标为i的元素值为e,返回其位序i+1
    return 0;
}
//时间复杂度:最好、最坏、平均 ==== O(1)、O(n)、O(n)


int main(){
    SqList L;    //声明一个顺序表
    InitList(L);    //初始化顺序表
    //......向顺序表中随意插入几个元素....
    IncreaseSize(L, 5);
    return 0;
}

 

3、带头结点单链表的实现

#include<stdlib.h>    //malloc、free函数的头文件

typedef struct LNode{
    ElemType data;   //每个结点存放一个数据元素
    struct LNode *next;    //指针指向下一个结点
}LNode, *LinkList;
/*
表示一个单链表,只需声明一个头指针L
LNode *L;    //强调这是一个结点
LinkList L;    //强调这是一个单链表
以上都能声明一个头结点,两句效果相同
*/


//初始化一个单链表(带头结点)
bool InitList(LinkList &L){
    L = (LNode *)malloc(sizeof(LNode));
    if(L==NULL)    //内存不足,分配失败
        return false;
    L->next=NULL;     //头结点之后没有结点
    return true;
}


//尾插法建立单链表
LinkList List_TailInsert(LinkList &L){
    int x;
    L=(LinkList)malloc(sizeof(LNode));    //创建头结点
    LNode *s,*r=L;
    scanf("%d",&x);
    while(x!=9999){    //输入结点值为9999表示结束
        s=(LNode *)malloc(sizeof(LNode));
        s->data=x;
        r->next=s;
        r=s;    //永远保持r在最后一个结点
        scanf("%d",&x);
    }
    r->next=NULL;
    return L;
}


//头插法建立单链表
LinkList List_HeadInsert(LinkList &L){
    LNode *s; int x;
    L=(LinkList)malloc(sizeof(LNode));    //创建头结点
    L->next=NULL;    //初始为空链表
    scanf("%d",&x);
    while(x!=9999){    //输入结点值为9999表示结束
        s=(LNode *)malloc(sizeof(LNode));
        s->next=x;
        s->next=L->next;
        L->next=s;
        scanf("%d",&x);
    }
    return L;
}
//头插法创建的链表输入的元素与实际存储顺序相反


//指定结点的后插操作
bool InsertNextNode(LNode *P, ElemType e){
    if(p==NULL)
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s==NULL)    //内存分配失败
        return false;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return true;
}


//指定结点的前插操作
bool InsertPriorNode(LNode *P, ElemType e){
    if(p==NULL)
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s==NULL)    //内存分配失败
        return false;
    s->next=p->next;
    p->next=s;      //将结点S插入
    s->data=p->data;     //将p与s的数据互换
    p->data=e;      //将e值覆盖p中元素
    return true;
}


//单链表按位查找,返回第i个元素
LNode * GetElem(LinkList L, int i){
    if(i<0)
        return false;
    LNode *p;    //指针p指向当前扫描到的结点
    int j=0;    //表示p指向的是第几个结点
    p=L;     //初始p指向头结点
    while(p!=NULL&&j<i){    //循环找到第i个结点
        p=p->next;
        j++;
    }
    return p;
}


//按值查找
LNode * LocateElem(LinkList L, ElemType e){
    LNode *p=L->next;
    while(p!=NULL&&p->data!=e)
        p=p->next;
    return p;
}


//按位序插入(带头结点)
bool ListInsert(LinkList &L, int i, ElemType e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i-1);    //找到第i-1个结点
    return InsertNextNode(p,e);
}


//删除指定结点P
bool DeleteNode(LNode *P){
    if(p==NULL||p->netx==NULL)    //P不能是最后一个结点
        return false;
    LNode *q=p->next;    //令q指向*p的后继结点
    p->data=p->next->data;    //和后继结点交换数据域
    p->next=q->next;    //将*q结点从链中断开
    free(q);
    return true;
}


//按位序删除(带头结点)
bool ListDelect(LinkList &L, int i, ElemType &e){
    if(i<1)
        return false;
    LNode *p=GetElem(L,i-1);    //找到第i-1个结点
    e=p->data;
    return DeleteNode(P);
}


//判断单链表是否为空(带头结点)
bool Empty(LinkList L){
    return(L->next==NULL);
}
//如果不带头结点,则是return(L==NULL);


void test(){
    LinkList L;    //声明一个指向单链表的指针
    //初始化一个空单链表
    InitList(L);
    return 0;
}

 

4、双链表的实现

#include<stdlib.h>

typedef struct DNode{
    ElemType data;
    struct DNode *prior,*next;
}DNode, *DLinkList;


//初始化一个双链表(带头结点)
bool InitDLinkList(DLinkList &L){
    L = (DNode *)malloc(sizeof(DNode));
    if(L==NULL)    //内存不足,分配失败
        return false;
    L->prior=NULL;    //头结点的prior永远指向NULL
    L->next=NULL;     //头结点之后暂时没有结点
    return true;
}


//双链表的插入--在p结点之后插入s结点
bool InsertNextDNode(DNode *p, DNode *s){
    if(p==NULL||s==NUll)
        return false;
    s->next=p->next;
    if(p->next!=NULL)    //如果p没有后继结点
        p->next->prior=s;
    s->prior=p;
    p->next=s;
}


//双链表的删除--删除p结点的后继结点
bool DeleteNextDNode(DNode *P){
    if(p==NULL)
        return false;
    DNode *q=p->next;
    if(q==NULL)
        return false;
    p->next=q->next;
    if(q->next!=NULL)
        q->next->prior=p;
    free(q);
    return ture;
}
void DestoryList(DLinkList &L){
    while(L->next!=NULL)
        DeleteNextDNode(L);
    free(L);
    L=NULL;
}


//判断双链表是否为空(带头结点)
bool Empty(DLinkList L){
    return(L->next==NULL);
}


void testDLinkList(){
    DLinkList L;
    InitDLinkList(L);
    ......
    return 0;
}

标签:结点,NULL,return,LNode,23,int,next,2021,数据结构
来源: https://blog.csdn.net/weixin_42637873/article/details/122650731