王道数据结构—线性表的存储结构和基本操作

线性表及其基本操作

一、顺序表示

#include<stdio.h>
/*动态分配的库*/
#include<stdlib.h>
/*静态分配
#define Maxsize 10
typedef struct{
    int data[Maxsize];
    int length;
}SqList;
//初始化
void InitList(SqList &L){
    for(int i=0;i<L.length;i++)
        L.data[i]=0;
    L.length=0;
}
*/
/*动态分配*/
#define InitSize 10     //默认最大长度
typedef struct{
    int *data;          //指示动态分配数组的指针
    int Maxsize;        //顺序表的最大容量
    int length;         //顺序表的当前长度
}SeqList;

/*初始化*/
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;                //p指针指向原顺序表所在存储空间
    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;      //顺序表最大长度增加len
    free(p);                      //释放临时空间
}

/*插入操作*/
bool ListInsert(SeqList &L,int i,int e){
    if(i<1||i>L.length+1)        //判断i的范围是否有效
        return false;
    if(L.length>=L.Maxsize){     //当存储空间已满,增加数组长度
        IncreaseSize(L,1);
        ListInsert(L,i,e);
    }
    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++;                  //线性表长度加1
    return true;
}

/*删除操作*/
bool ListDelete(SeqList &L,int i,int &e){
    if(i<1||i>L.length)          //判断i的范围是否有效
        return false;
    e=L.data[i-1];               //将被删除的元素赋值给e
    for(int j=i;j<L.length;j++)  //将第i个位置后的元素前移
        L.data[j-1]=L.data[j];
    L.length--;                  //线性表长度减1
    return true;
}

/*按值查找*/
int LocateElem(SeqList L,int e){
    int i;
    for(i=0;i<L.length;i++)
        if(L.data[i]==e)
           return i+1;      //下标为i位序为i+1
    return 0;               //推出循环,查找失败
}

/*按位查找*/
int GetElem(SeqList L,int i){
    return L.data[i-1];
}

int main(){
    int temp;
    int Locate;
    SeqList L;
    InitList(L);
    IncreaseSize(L,5);
    for(int i=1;i<8;i++)
        ListInsert(L,i,i);
    for(int i=0;i<7;i++)
        printf("%d\n",L.data[i]);
    printf("此时顺序表长度为%d\n",L.length);
    ListDelete(L,4,temp);
    printf("删除了第4个元素,其值为%d\n",temp);
    printf("此时顺序表长度为%d\n",L.length);
    Locate=LocateElem(L,6);
    printf("值为6的元素在顺序表中的位置为%d\n",Locate);
    return 0;
}


二、链式表示

1、单链表

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;
//初始化
bool InitList(LinkList &L){
    L=(LNode*)malloc(sizeof(LNode));
    if(L==NULL)
        return false;
    L->next=NULL;
    return true;
}

//判空
bool Empty(LinkList L){
    return(L->next==NULL);
}

//头插法
LinkList List_HeadInsert(LinkList &L){
    LNode *s;
    int x;
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    scanf("%d",&x);
    while(x!=9999){
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;
        s->next=L->next;
        L->next=s;
        scanf("%d",&x);
    }
    return L;
}

//尾插法
LinkList List_TailInsert(LinkList &L){
    int x;
    L=(LinkList)malloc(sizeof(LNode));
    LNode *s,*r=L;
    scanf("%d",&x);
    while(x!=9999){
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;
        r->next=s;
        r=s;
        scanf("%d",&x);
    }
    r->next=NULL;
    return L;
}

//指定结点前插操作
bool InsertPriorNode(LNode *p,int 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->data=p->data;
    p->data=e;
    return true;
}

//指定结点后插操作
bool InsertNextNode(LNode *p,int 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;
}

//按位查找
LNode *GetElem(LinkList L,int i){
    if(i<0)
        return false;
    LNode *p;
    int j=0;
    p=L;
    while(p!=NULL&&j<i){
        p=p->next;
        j++;
    }
    return p;
}

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

//指定位置插入元素
bool ListInsert(LinkList &L,int i,int e){
    if(i<1)
        return false;
    LNode *p;
    p=GetElem(L,i-1);
    return InsertNextNode(p,e);
}

//指定位置删除元素
bool ListDelete(LinkList &L,int i,int &e){
    if(i<1)
        return false;
    LNode *p;
    p=GetElem(L,i-1);
    if(p==NULL)
        return false;
    if(p->next==NULL)
        return false;
    LNode *q=p->next;
    e=q->data;
    p->next=q->next;
    free(q);
    return true;
}

//指定结点删除
bool DeleteNode(LNode *p){
    if(p==NULL)
        return false;
    LNode *q=p->next;
    p->data=p->next->data;
    p->next=q->next;
    free(q);
    return true;
}

//求链表长度
int GetLength(LinkList L){
    LNode *p;
    int sum=0;
    p=L;
    while(p->next!=NULL){
        sum++;
        p=p->next;
    }
    free(p);
    return sum;
}

//打印链表
void PrintList(LinkList L){
    LNode* p=L;
    while(p->next!=NULL){
        p=p->next;
        printf("%d ",p->data);
    }
    printf("\n");
}

int main(){
    LinkList L;
    LNode *s;
    int x,y,num;
    printf("创建链表,输入9999结束\n");
    List_HeadInsert(L);//头插法逆序
    //List_TailInsert(L)//尾插法正序
    PrintList(L);
    printf("在第2个结点(不含头结点)的前面添加携带值为10的结点\n");
    InsertPriorNode(L->next->next,10);
    PrintList(L);
    printf("在第1个结点(不含头结点)的后面添加携带值为11的结点\n");
    InsertNextNode(L->next,11);
    PrintList(L);
    s=GetElem(L,3);
    printf("链表中第3个元素(不含头结点)的值为:%d\n",s->data);
    x=LocateElem(L,5);
    printf("链表中值为5的元素所在位置为:%d\n",x);
    printf("在链表第3个结点处插入17\n");
    ListInsert(L,3,17);
    PrintList(L);
    printf("删除链表中第5个结点\n");
    ListDelete(L,5,y);
    printf("被删除后的链表中元素为:");
    PrintList(L);
    printf("被删除结点的元素值为:%d\n",y);
    num=GetLength(L);
    printf("当前链表长度为:%d\n",num);
    return 0;
}



2、双链表

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct DNode{
    int data;
    struct DNode *prior,*next;
}DNode,*DLinkList;

//前插法
DLinkList List_HeadInsert(DLinkList &L){
    DNode *s;
    int x;
    L=(DLinkList)malloc(sizeof(DNode));
    L->next=NULL;
    scanf("%d",&x);
    while(x!=9999){
        s=(DNode*)malloc(sizeof(DNode));
        s->data=x;
        s->next=L->next;
        s->prior=L;
        L->next=s;
        scanf("%d",&x);
    }
    return L;
}

//按位置查找结点
DNode *GetElem(DLinkList L,int i){
    if(i<1)
        return false;
    DNode *p;
    int j=0;
    p=L;
    while(p!=NULL&&j<i){
        p=p->next;
        j++;
    }
    return p;
}

//指定结点后插入结点
bool InsertNextNode(DNode *p,DNode *s){
    s->next=p->next;
    p->next->prior=s;
    p->next=s;
    s->prior=p;
}

//删除指定结点的后继结点
int DeleteNextNode(DNode *p){
    int e;
    if(p==NULL) return -1;
    DNode *q=p->next;
    if(q==NULL) return -1;
    e=p->next->data;
    p->next=q->next;
    if(q->next!=NULL)
        q->next->prior=p;
    free(q);
    return e;
}

//销毁双链表
void DestroyList(DLinkList &L){
    while(L->next!=NULL)
        DeleteNextNode(L);
    free(L);
    L=NULL;
}

//打印双链表
void PrintList(DLinkList L){
    DNode* p=L;
    while(p->next!=NULL){
        p=p->next;
        printf("%d ",p->data);
    }
    printf("\n");
}

int main(){
    DLinkList L;
    DNode *s,*p;
    int x;
    printf("创建双链表,输入9999结束\n");
    List_HeadInsert(L);
    PrintList(L);
    s=GetElem(L,3);
    printf("双链表第3个结点的值为:%d\n",s->data);
    p=(DNode*)malloc(sizeof(DNode));
    p->data=10;
    p->prior=p->next=NULL;
    InsertNextNode(s,p);
    printf("在双链表第3个结点后插入值为10的元素后的双链表如下:\n");
    PrintList(L);
    x = DeleteNextNode(s);
    printf("删除双链表第3个结点后继结点后的双链表如下:\n");
    PrintList(L);
    printf("被删除结点的值为:%d\n",x);
    return 0;
}

3、循环链表

3-1、循环单链表
在这里插入代码片
3-2、循环双链表
在这里插入代码片

4、静态链表

#define MaxSize 50   //静态链表的最大长度
typedef struct{      //静态链表结构类型的定义
   ElemType data;    //存储数据元素
   int next;         //下一个元素的数组下标
}SLinkList[MaxSize];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值