数据结构(三)线性表之单链表

一、链表的定义和的特点

  • 线性表的链式存储又称单链表,它是通过一组任意的存储单元来存储线性表中的数据元素。
  • 每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针
  • 头结点和头指针的区分:不管带不带头结点,头指针都始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,头结点内通常不存储信息。
  • 头结点的优点:1. 由于第一个数据结点的位置被存放在头结点的指针域中,因此在链表的第一个位置上的操作和在表的其他位置上的操作一致,无须进行特殊处理。2. 无论链表是否为空,其头指针都指向头结点的非空指针(空表中头结点的指针域为空),因此空表和非空表的处理也就得到了统一。
  • 插入和删除操作不需要移动元素,而只需修改指针,但也会失去顺序表可随机存取的优点

二、链表的基本操作

#include<iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef struct LNode{
    int data;
    struct LNode* next;
}LNode, *LinkList; //这里LNode 和 *LinkList 等价,只不过LNode更强调一个结点,LinkList更强调一个链表。

LinkList List_HeadInsert(LinkList &L); //头插法建立单链表(逆向建立单链表)
LinkList List_TailInsert(LinkList &L); //尾插法(正向建立单链表)
LNode *GetElem(LinkList L,int i); //按序号查找结点值
LNode *LocateElem(LinkList L,int e); //按值查找表结点
bool ListInsert(LinkList &L,int i,int e); //在第i个位置插入元素e
bool ListDelete(LinkList &L,int i,int &e); //按位序删除,并用e带回结点data

LinkList List_HeadInsert(LinkList &L)
{
    LNode *s;
    int x;
    L = (LinkList)malloc(sizeof(LNode)); //创建头结点
    L->next = NULL; //初始为空链表
    cin>>x; //输入结点的值
    while (x!=9999) { //输入9999表示结束
        s = (LNode*)malloc(sizeof(LNode)); //创建新结点
        s -> data = x;
        s -> next = L -> next;
        L -> next = s; //将新结点插入表中,L为头指针
        cin>>x;
    }
    return L;
}

LinkList List_TailInsert(LinkList &L)
{
    int x;
    L = (LinkList)malloc(sizeof(LNode));
    LNode *s,*r=L; //r为表尾指针,指向链表最后一个结点(最后一个结点的next域始终为空)
    cin>>x;
    while (x!=9999) {
        s = (LNode*)malloc(sizeof(LNode));
        s -> data = x;
        r -> next = s;
        r = s; //尾指针指向新的尾结点
        cin>>x;
    }
    r -> next = NULL;
    return L;
}

LNode *GetElem(LinkList L,int i)
{
    int j=1;
    LNode *p = L -> next;
    if(i==0)
    {
        return L;
    }
    if(i<1)
    {
        return NULL;
    }
    while (p && j<i) {
        p = p -> next;
        j++;
    }
    return p;
}

LNode *LocateElem(LinkList L,int e)
{
    LNode *p = L -> next;
    while ((p != NULL) && (p -> data !=e)) {
        p = p -> next;
    }
    return p;
}

bool ListInsert(LinkList &L,int i,int e)
{
    if(i<1)
    {
        return false;
    }
    LNode *p; //指针p指向当前扫描到的结点
    int j = 0; //当前p指向的是第几个结点
    p = L; //L指向头结点,头结点是第0个结点(不存数据)
    while (p != NULL && j<i-1) { //循环找到第 i-1 个结点
        p = p -> next;
        j++;
    }
    if(p==NULL) //i值不合法
    {
        return false;
    }
    
    LNode *s = (LNode*)malloc(sizeof(LNode));
    s -> data = e;
    s -> next = p -> next;
    p -> next = s;
    return true;
}

bool ListDelete(LinkList &L,int i,int &e)
{
    if(i<1)
        return false;
    LNode *p; //指针p指向当前扫描到的结点
    int j = 0; //j表示当前第几个结点
    p = L; //L为链表头指针
    while (p != NULL && j<i-1) { //循环到要删除的结点的前一个结点
        p = p -> next;
        j++;
    }
    if(p == NULL) //i值不合法
        return false;
    if(p -> next == NULL) //如果是最后一个结点
        return false;
    LNode *q = p -> next; //令q指向被删除结点
    e = q -> data; //用e返回元素的值
    p -> next = q -> next; //将*q结点从链中断开
    free(q); //释放结点的存储空间
    return true;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值