数据结构之单链表

链表:逻辑上是连续的,再物理空间上不是连续的(每个数据存储的空间都是单独申请的)

结点结构:数据元素+指针域

单链表:只有一个指针域,存储下一个结点的地址

1、带头节点的单链表:

第一个结点不存储数据元素,只是利用其指针域来存储整个链表的起始(将头节点直接定义在栈区且头节点在正式操作链表之前就已经存在,其余结点定义在堆区)

结构:

typedef int ElemType;

typedef union DataType
{
    ElemType value;
    int num;
}DataType;

typedef struct LNode
{
    DataType data;//数据元素
    struct LNode *next;//存储下一个数据节点的地址
}LNode,*LinkList;

初始化:

void Init_LinkList(LinkList head)
{
    assert(head != NULL);
    if(head == NULL) exit(0);
    
    head->next = NULL;
    head->data.num = 0;
}

功能实现:插入(头插、按位插入、尾插),删除(头删、尾删、按位删除),打印,销毁

//申请一个结点
static LinkList ApplyNode(ElemType val,LinkList next)
{
    LinkList new_node = (LinkList)malloc(sizeof(LNode));
    if(new_node == NULL)
        return NULL;
    new_node->next = next;
    new_node->data.value = val;
    return new_node;
}
//查找目标位置的前一个位置
static LinkList FindPrior(LinkList head,int pos)
{
    LinkList p = head;
    while(pos > 0)
    {
        p = p->next;
        pos--;
    }
    return p;
}
//插入(按位插入)
int Insert_LinkList_Pos(LinkList head,ElemType val,int pos)
{
    assert(head != NULL);
    if(head == NULL) exit(0);
    
    if(pos < 0 || pos > head->data.num)
        return false;
    LinkList p = FindPrior_Pos(head,pos);
    LinkList new_node = ApplyNode(val,p->next);
    if(new_node == NULL)
        return false;
    p->next = new_node;
    head->data.num++;
    return true;
}
//头插
int Insert_LinkList_Head(LinkList head,ElemType val)
{
    return Insert_LinkList_Pos(head,val,0);
}
//尾插
int Insert_LinkList_Tail(LinkList head,ElemType val)
{
    assert(head != NULL);
    if(head == NULL ) exit(0);
    return Insert_LinkList_Pos(head,val,head->data.num);
}

//删除结点(按位删)
int Delete_LinkList_Pos(LinkList head,int pos)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    if(pos < 0 || pos >= head->data.num)
        return false;
    LinkList p = FindPrior(head,pos);
    LinkList q = p->next;
    p->next = q->next;
    free(q);
    head->data.num--;
    return true;
}
//头删
int Delete_LinkList_Head(LinkList head)
{
    return Delete_LinkList_Pos(head,0);
}
//尾删
int Delete_LinkList_Tail(LinkList head)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    return Delete_LinkList_Pos(head,head->data.num-1);
}

//打印
void Show(LinkList head)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    LinkList p = head->next;
    while(p)
    {
        printf("%d ",p->data.value);
        p = p->next;
    }
    peintf("\n");
}

//清除
int Clear_LinkList(LinkList head)
{
    while(head->data.num)
    {
        if(!Delete_LinkList_Head(head))
            return false;
    }
    return true;
}
//销毁
int Destory_LinkList(LinkList head)
{
    return Clear_LinkList(head);
}

2、不带头节点的单链表

定义链表时定义的是一个头指针,这个指针将来指向第一个数据结点

结构:

typedef int ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

初始化:

void Init_LinkList(LinkList *head)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    *head->next = NULL;
}

功能:插入(头插、尾插、按位插入),删除(头删、尾删、按位删除),打印

//寻找目标位置的前一个结点的位置
static int FindPrior(LinkList head,int pos)
{
    LinkList p = head;
    while(pos - 1)
    {
        p = p->next;
        pos--;
    }
    return p;
}
//申请新结点
static int ApplyNode(ElemType val,LinkList *next)
{
    LinkList new_node = (LinkList)malloc(sizeof(LNode));
    if(new_node == NULL) 
        return false;
    
    new_node->data = val;
    new_node->next = next;
    return new_node;
}
//获取LinkList的长度
static int GetLinkListLength(LinkList *head)
{
    LinkList p = head;
    int length = 0;
    while(p != NULL)
    {
        length++;
        p = p->next;
    }
    return length;
}
//头插
int Insert_LinkList_Head(LinkList *head,ElemType val)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    LinkList p = ApplyNode(val,*head);
    *head = p;
    return true;
}
//按位插入数据
int Insert_LinkList_Pos(LinkList *head,ElemType val,int pos)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    if(pos < 0 || pos > GetLinkListLength(head))
        return false;
    if(pos == 0)
        return Insert_LinkList_Head(head,val);
    LinkList p = FindPrior(*head,pos);//找到目标位置的前一个位置,在其后插入新结点
    LinkList q = ApplyNode(val,p->next);//申请新结点
    p->next = q;

    return true;
}
//尾插
int Insert_LinkList_Tail(LinkList *head,ElemType val)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    return Insert_LinkList_Pos(head,val,GetLinkListLength(head));
}
//头删
int Delete_LinkList_Head(LinkList *head)
{
    assert(head != NULL);
    if(head == NULL || *head == NULL) exit(0);//*head指链表是否为空
    
    LinkList p = *head;
    *head = p->next;
    free(p);
    return true;
}
//按位删除
int Delete_LinkList_Pos(LinkList *head,int pos)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    if(pos < 0 || pos >= GetLinkListLength(head))
        return false;
    if(pos == 0)
        return Delete_LinkList_Head(head);
    LinkList p = FindPrior(*head,pos);
    LinkList q = p->next;
    p->next = q->next;
    free(q);
    return true;
}
//尾删
int Delete_LinkList_Tail(LinkList *head)
{
    assert(head != NULL);
    if(head == NULL) exit(0);

    return Delete_LinkList_Pos(head,GetLinkListLength(head)-1);
}
//打印
void Show_LinkList(LinkList head)
{
    assert(head != NULL);
    if(head == NULL) exit(0);
    
    LinkList p = head;
    while(p != NULL)
    {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值