【数据结构】(动态/静态)链表的基本操作

1. 动态链表实现

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

#include <stdio.h>
#include <stdlib.h>

typedef int Status;
typedef int ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;
/*
    单链表的初始化
    构造一个带头结点的空链表
    L- head pointer
*/
Status InitLList(LinkList &L)
{
    L = (LNode*) malloc(sizeof(LNode)); //新生成结点作为头结点 用头指针L指向头结点
    L->next = NULL;                     //头指针的next域设置为空

    if(L) //内存分配成功
    {
        return OK;
    }
    else  //内存分配失败
    {
        return ERROR;
    }
}

/*
    获取带头结点单链表中指定序号元素
    L-head pointer
    i-order of element
    e-element
*/
Status GetLListElem(LinkList L, int i, ElemType &e)
{
    LNode *p = L->next; //指向某结点的指针p  此时指向首元结点
    int j = 1; //初始化计数器为1

    //找到i的前一个结点
    while(p && j < i)
    {
        j++;
        p = p->next;
    }

    if(!p || j > i) //i不合法 i<=0 i>n
    {
        return ERROR;
    }

    e = p->data;//找到了

    return OK;
}

/*在带头结点的单链表中查找元素值为e的元素*/
LNode *LocLListElem(LinkList L, const ElemType &e)
{
    LNode *p = L->next;

    while(p && p->data !=e)
    {
        p = p->next;
    }

    return p;//成功,返回指针不为空  失败 返回NULL
}

/*在带头结点的单链表中的i位置插入元素e*/
Status InsertLList(LinkList &L, int i, const ElemType &e)
{
    LNode *p = L;//指针p指向头结点,因为有可能在首元结点前插入
    //需要找到待插入节点的前一个节点
    int j = 0;

    //找到第i-1个节点
    while(p && j< i-1)
    {
        p = p->next;
        j++;
    }
    //此时p指向第i-1个节点
    if(!p || j > i - 1)  //i > n || i<1
    {
        return ERROR;
    }
    //生成新节点
    LNode *s = (LNode*)malloc(sizeof(LNode));

    if(s) //内存申请成功
    {
        s->data = e;
        s->next = p->next; //结点s指向p的下一个节点
        p->next = s;//结点p指向s
    }
    else
    {
        return ERROR;
    }

    //插入成功
    return OK;
}

/*删除带头结点的单链表的第i个节点*/
Status DeleteLList(LinkList &L, int i)
{
    LNode *p = L; //p指向头结点 需要定位到第i-1个节点
    int j = 0;

    while(p && j < i - 1)
    {
        p = p->next;
        j++;
    }//此时p指向的节点是第i-1个节点

    if(!p || j > i - 1) //i>n || i<1
    {
        return ERROR;
    }

    //删除成功
    LNode *s = p->next;//被删除的结点
    p->next = s->next; //p指向被删除节点的下一个节点

    free(s);//释放被删除的节点
    s = NULL;//指向空

    return OK;
}

/*前(头)插法创建带头结点的单链表 n个节点*/
Status CreateList_H(LinkList &L, int n)
{
    LNode *p;

    for(int i = n; i > 0; i--)
    {
        p = (LNode *)malloc(sizeof(LNode)); //p 指向新申请的待创建结点
        if(p != NULL) //内存申请成功
        {
            int data;
            scanf("%d",&data);
            p->data = data;
            p->next = L->next;//新插入的结点始终指向头结点的下一个结点
            L->next = p;//头结点next指针始终指向新插入的结点
        }
        else
        {
            return ERROR;
        }
    }

    return OK;
}

/*后(尾)插法创建带头结点的单链表 n个节点*/
Status CreateList_R(LinkList &L, int n)
{
    LNode *r; //尾指针 指向最后一个结点
    r = L;//尾指针初始化指向头结点

    LNode *p;//指向待创建结点的指针

    for(int i = n; i > 0; i--)
    {
        p = (LNode*)malloc(sizeof(LNode));
        if(p)
        {
            int data;
            scanf("%d",&data);

            p->data = data;
            r->next = p;//尾指针指向的结点(尾结点)的下一个节点始终是新创建的结点
            r = p;//尾指针指向每次新创建的结点
        }
        else
        {
            return ERROR;
        }
    }
    r->next = NULL;
    return OK;
}

/*遍历带头结点单链表中的结点*/
void TraverseLList(LinkList L)
{
    LNode *p = L->next;
    while(p->next)
    {
        printf("%d",p->data);
        printf("->");
        p = p->next;
    }
    printf("%d",p->data);
}

/*有序链表的合并
带头结点的单链表 LA LB 元素值按非递减顺序排列
合并得到的新链表LC也是有序排列 非递减顺序
*/
void MergeLList(LinkList &LA, LinkList &LB, LinkList &LC)
{
    LNode *pa = LA->next;
    LNode *pb = LB->next;
    LNode *pc = LA; //pc指针指向LA链表头结点
    LC = pc;//同时LC的头指针指向pc

    while(pa && pb)
    {
        if(pa->data <= pb->data) //pa元素小于pb指向的元素
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    //pa 为空 或 pb 为空
    pc->next = pa ? pa : pb;//剩余元素直接插入LC

    free(LB);//释放LB的头结点
}

/*释放链表结点*/
void FreeLList(LinkList &L)
{
	LNode *p = L;
	LNode *temp = NULL;

	while(p)
	{
	    temp = p->next;
		free(p);
		p = NULL; //指针要指向空
		p = temp;
	}//头结点 也被释放了 不用单独释放

	//LNode定义的p temp都是指针变量 属于局部变量,在栈内存中,程序动态释放

}

int main()
{
    /*LinkList L;
    int mode;
    while(true)
    {

        printf("请输入创建带头结点单链表的方式(0-前/头插法,1-后/尾插法):");
        scanf("%d",&mode);
        if(mode == 0 || mode == 1)
        {
            break;
        }
        else
        {
            printf("输入不合法,请重新输入!\n");
        }
    }
    printf("请输入创建带头结点单链表的结点个数(node_num > 0):");
    int node_num;
    scanf("%d",&node_num);
    printf("请输入要创建的结点:");
    InitLList(L);
    if(mode == 0)
    {
        CreateList_H(L,node_num);
    }
    else if(mode == 1)
    {
        CreateList_R(L,node_num);
    }
    TraverseLList(L);
    printf("\n");

    printf("请输入你要删除的结点位置(1~结点总数):");
    int i;
    scanf("%d",&i);
    DeleteLList(L,i);

    TraverseLList(L);
    printf("\n");

    printf("请输入你要插入的结点位置(1~结点总数)及元素(int整数):");
    int j,e;
    scanf("%d%d",&j,&e);
    InsertLList(L,j,e);

    TraverseLList(L);
    printf("\n");

    printf("请输入你要查找的元素的位置(1~结点总数):");
    int k;
    scanf("%d",&k);
    GetLListElem(L,k,e);
    printf("你查找的元素是:%d \n",e);

    printf("请输入你要查找的元素(int整数):");
    int e1;
    scanf("%d",&e1);
    LNode *p = LocLListElem(L,e1);
    if(p)
    {
        printf("查找成功!\n");
    }
    else
    {
        printf("查找失败,元素不存在!\n");
    }

    FreeLList(L);*/

    //链表的应用 合并链表
    printf("合并链表:\n");
    printf("请输入创建链表A的结点个数:");
    int na;
    scanf("%d",&na);
    printf("请输入要创建链表A的结点:");
    LinkList LA;
    InitLList(LA);
    CreateList_R(LA,na);

    printf("请输入创建链表B的节点个数:");
    int nb;
    scanf("%d",&nb);
    printf("请输入要创建链表B的结点:");
    LinkList LB;
    InitLList(LB);
    CreateList_R(LB,nb);

    printf("合并之后的链表LC:");
    LinkList LC;
    InitLList(LC);
    MergeLList(LA, LB, LC);
    TraverseLList(LC);

    FreeLList(LA);
    FreeLList(LB);
    FreeLList(LC);

    return 0;
}

2. 静态链表实现

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXSIZE 20

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;
typedef int Status;

typedef struct
{
    ElemType data;
    int cur;
} component, SLinkList[MAXSIZE];

/*
    初始化备用链表
    将所有未使用过的、删除的分量用游标做成一个备用链表
    space[0].cur为备用空闲链表的头指针
    0 表示空
*/
void InitSpace(SLinkList &space)
{
    space[0].cur = 2; //表示备用链表头结点
    space[0].data = -1;
    space[1].cur = -1;//表头结点 还没存数据
    space[1].data = -1;
    for(int i = 2; i < MAXSIZE - 1; i++)
    {
        space[i].cur = i + 1;
        space[i].data = -1;
    }
    space[MAXSIZE - 1].cur = 0;
    space[MAXSIZE - 1].data = -1;
}

/*
    在静态单链表中查找值为e的元素
    e = S[i].data
*/
int LocSListElem(SLinkList S, ElemType e)
{
    int i = S[1].cur;//从表头结点开始找
    while(i && S[i].data != e)
    {
        i = S[i].cur;
    }

    return i;
}

/*malloc 静态链表分配结点空间*/
int Malloc(SLinkList &space)
{
    //备用链表非空 则返回分配结点的下标 否则返回0
    int i = space[0].cur;
    if(space[0].cur != 0)
    {
        space[0].cur = space[i].cur;
    }
    return i;
}

/*释放下标为k的空闲结点 回收到备用链表*/
void Free(SLinkList &space, int k)
{
    space[k].cur = space[0].cur;
    space[k].data = -1;
    space[0].cur = k;
}

/*
    删除静态链表的第i个元素
*/
Status DeleteSList(SLinkList &space, int i)
{
    int j = 1; //头指针指向头结点
    int k = 0;
    while(j !=0 && k < i - 1)
    {
        j = space[j].cur;
        k++;
    }
    if(space[j].cur == 0 || k >= i || i <= 0)
    {
        return ERROR;
    }
    //k == i - 1; j是第i - 1个元素的下标
    component c = space[space[j].cur]; //第i个节点
    Free(space, space[j].cur);//释放该结点
    space[j].cur = c.cur;
    return OK;
}

/*
    在链表中第i个元素之前插入元素 e
*/
Status InsertSList(SLinkList &space,int i, ElemType e)
{
    int j = 1; //头指针指向头结点
    int k = 0;
    while(j !=0 && k < i - 1)
    {
        j = space[j].cur;
        k++;
    }

    if(space[j].cur == 0 || k > i || i <= 0)
    {
        return ERROR;
    }
    //k == i - 1; j是第i - 1个元素的下标
    int idx = Malloc(space);
    space[idx].data = e;
    space[idx].cur = space[j].cur;
    space[j].cur = idx;

    return OK;
}

/*创建含有n个节点的静态链表*/
void CreateSList(SLinkList &space,int n)
{
    space[1].cur = 2;
    for(int i = 0; i < n; i++)
    {
        int idx = Malloc(space);
        ElemType e;
        scanf("%d", &e);
        space[idx].data = e;
        if( i == n - 1)
            space[idx].cur = 0;
    }
}


void TraverseSList(SLinkList &space)
{
    for(int i = 0; i < 20; i++)
    {
        printf("%10d ",i);
        printf("%10d ",space[i].data);
        printf("%10d \n",space[i].cur);
    }
}

int main()
{
    SLinkList space;
    InitSpace(space);
    int n;
    printf("请输入您要创建的静态链表元素的个数(>0):");
    scanf("%d", &n);
    printf("请输入您要创建的静态链表的元素:");
    CreateSList(space,n);
    printf("您创建的静态链表:\n");
    TraverseSList(space);
    printf("\n");

    int insert_i;
    printf("请输入您要插入的元素的位置(>0):");
    scanf("%d",&insert_i);
    int insert_e;
    printf("请输入您要插入的元素:");
    scanf("%d", &insert_e);
    if(InsertSList(space, insert_i, insert_e))
    {
        printf("插入成功!\n");
        printf("插入之后的静态链表:\n");
        TraverseSList(space);
        printf("\n");
    }
    else
    {
        printf("插入失败!\n");
    }

    int delete_i;
    printf("请输入您要删除的元素的位置(>0):");
    scanf("%d", &delete_i);
    if(DeleteSList(space, delete_i))
    {
        printf("删除成功!\n");
        printf("删除之后的静态链表:\n");
        TraverseSList(space);
    }
    else
    {
        printf("删除失败!\n");
    }

    return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
静态链表是一种使用数组实现的链表结构。它通过数组中的元素自身的指针来实现链表的连接关系。以下是静态链表基本操作: 1. 初始化:创建一个包含足够多元素的数组,每个元素包含两个字段,一个用于存储数据,另一个用于存储指向下一个元素的索引。初始化时,设置数组中所有元素的指针字段为-1,表示链表为空。 2. 插入:插入操作将新元素插入到静态链表中的指定位置。首先找到一个空闲位置并将新元素插入其中,然后将前一个元素的指针字段指向新元素,在将新元素的指针字段指向原来位置的后继元素。 3. 删除:删除操作静态链表中指定位置的元素移除。首先将要删除的元素的前一个元素的指针字段指向要删除元素的后继元素,然后将要删除元素所在位置设置为空闲。 4. 查找:查找操作可以根据给定的关键字或索引在静态链表中找到对应的元素。可以通过遍历整个链表,逐个比较每个节点中存储的值与给定关键字或索引进行匹配。 5. 更新:更新操作用于修改静态链表中指定位置元素的值。首先找到要更新的元素位置,然后将其值进行修改。 需要注意的是,静态链表的插入和删除操作可能需要额外的空间来存储空闲位置的索引信息,以便快速找到可用位置。另外,由于静态链表使用数组实现,插入和删除操作可能会涉及元素的移动,因此效率较低,适用于对数据的频繁查找而不是插入和删除的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值