从零开始的数据结构(C语言)——单链表

从零开始的数据结构(C语言)——链表

相关说明

链表是线性表的链式存储结构,其特点是一组数据元素的存储单元可以不连续。每个元素是一个对象,每个对象包括了两个域,即数据域和指针域,其中对于单链表而言,其指针域存储表示当前的点的后继存储位置的指针。(本章采用带头结点的单链表进行演示)

  • 假设x为链表中的一个元素,则x->next则指向后继元素。
  • 在链表中,除头节点外的每个节点都有且只有一个前驱元素,除尾节点外的每个节点都有且只有一个后继元素。
  • 头指针表示链表的第一个节点、NULL表示链表的最后一个节点

单链表

单链表的定义

typedef int ElemType;
typedef struct LNode{
    ElemType data;//数据域
    struct LNode *next;//指针域
}LNode, *LinkList;//一般LNode* 用于定义任意节点的指针变量,LinkList用于定义头指针变量

单链表的基本操作

初始化单链表
int initList(LinkList &L)
{
    L = (LinkList)malloc(sizeof(LNode));//为头指针开辟空间
    L->next = NULL;//指针域置空
    return 1;
}
查找

序号查找

查找第i(i>=1)个节点

int getElemList(LinkList L, int i, ElemType &e)
{
    LNode* p = L->next;//防止头指针丢失,获取第一个有效节点
    int j = 1;
    while(p && j<i)//扫描
    {
        j++;
        p = p->next;
	}
    if(!p || j>i)//若p为空则说明不存在这样的节点;若j>i则说明i<1,不符合规范
    {
        return -1;
    }
    e = p->data;
    return 1;
}

按值查找

LNode* locateElemList(LinkList L, ElemType e)
{
    LNode*p = L->next;
    while(p&&p->data != e)
    {
        p = p->next;
    }
    return p;//当p为NULL时说明查找失败,反之查找成功
}
插入

将值为e的新节点插入到第i个节点位置

int insertElemList(LinkList &L, ElemType e, int i)
{
    LNode*p = L;
    int j = 0;
    while(p&&j<i-1)
    {
        p = p->next;
        i++;
    }
    if(!p||j>i-1)
    {
        return -1;
    }
    LNode *s = (LinkList)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return 1;
}
删除

将单链表的第i个节点删除

需要先找到第i-1个节点,将i-1节点的指针域指向第i+1个节点

int deleteElemList(LinkList &L, ElemType e, int i)
{
    LNode*p = L;
    int j = 0;
    while(p->next&&j<i-1)
    {
        p = p->next;
        j++;
	}
    if(!p->next || j>i-1)
        return -1;
    LNode* temp = p->next;
    p->next = temp->next->next;
    delete temp;
    return 1;
}

单链表的创建

头插法

头插法数据读写顺序相反

void CreateList_F(LinkList &L, int n)
{
    L = (LinkLIst)malloc(sizeof(LNode));
    L->next = NULL;
    for(int i=0;i<n;i++)
    {
        LNode* s = (LNode*)malloc(sizeof(LNode));
        cin >> p->data;
        p->next = L->next;
        L->next = p;
	}
}
尾插法

尾插法数据读写顺序相同

void CreateList_L(LinkList &L, int n)
{
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    LNode*r = L;
    for(int i=0;i<n;i++)
    {
        LNode*s = (LNode*)malloc(sizeof(LNode));
        cin >> p->data;
        p->next = NULL;
        r->next = p;
        r = p;
    }
}

单链表的转置

void swapElemList(LinkList &L)
{
	LNode* p = L->next;
    LNode *temp, *s = NULL;//temp用于暂存节点位置,s用于表示转置后链表的一个节点
    while(p)
    {
        temp = p->next;//记录下一个节点的位置
        p->next = s;
        s = p;
        p = temp;
    }
    L->next = s;
}

单链表合并

有序的两个单链表合并成一个单链表

void mergeElemList(LinkList &L1, LinkList &L2, LinkList &L3)
{
    LNode* p1 = L1->next;
    LNode* p2 = L2->next;
    L3 = L1;
    LinkList p3 = L3;
    //比较,选取较小的节点插入L3
    while(p1&&p2)//当两个单链表中的某个单链表的所有节点都已经合并入了L3中,退出
    {
        if(p1->data<=p2->data)
        {
            p3->next = p1;
            p3 = p1;
            p1 = p1->next;
        }
        else
        {
            p3->next = p2;
            p3 = p2;
            p2 = p2->next;
		}
	}
    pc->next = p1? p1:p2;//当p1非空则插入p1,否则插入p2
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值