线性表(List)---链式存储结构(单向链表)

来源:互联网 发布:淘宝老顾客回购率 编辑:程序博客网 时间:2024/05/14 13:25

单向链表设计与实现


链式存储的基本介绍

链式存储定义: 为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身信息外,还需要存储指示其直接后继的信息。

链式存储结构定义

  • 表头结点: 链表中第一个结点,包含指向第一个数据匀速的指针,以及链表自身的一些信息。
  • 数据结点: 链表中代表数据元素的结点,包含指向下一个数据元素的指针和信息。
  • 尾结点 : 链表中最后一个数据结点,其下一个元素指针为空表表示无后继结点。

链表的种类

  • 传统链表
    传统链表
  • 非传统链表(linux内核链表)
    非传统链表(linux内核链表)

单链表的设计

定义一个结构体指针用来存储指针与指针之间的关系:

typedef struct _tag_LinkListNode{    struct _tag_LinkListNode *next;}LinkListNode;

定义一个头结点用来存储链表:

typedef struct _tag_LinkList{    LinkListNode *header;    int length;}TLinkList;

数据元素定义实例:

 struct Value{    LinkListNode node;     int  v; };

单向链表的重要算法

  • 单向链表的插入算法
    • 插入前
      单向链表插入算法前
    • 插入后
      单向链表插入算法后
  • 单向链表的删除算法
    • 删除前
      单向链表删除算前
    • 删除后
      单向链表删除算后

单向链表的优缺点

  • 优点:
    • 无需一次性定制链表的容量
    • 插入和删除操作无需移动数据
  • 缺点:
    • 数据元素必须保存后继元素的位置信息
    • 获取指定数据元素操作需要访问之间的元素

单向链表的实现

LinkList.h

#ifndef _LINKLIST_H_#define _LINKLIST_H_typedef void LinkList;typedef struct _tag_LinkListNode{    struct _tag_LinkListNode *next;}LinkListNode;//创建链表LinkList *LinkList_Create();//销毁链表void LinkList_Destroy(LinkList *list);//清空链表void LinkList_Clear(LinkList *list);//获取链表的长度int LinkList_Length(LinkList *list);//向链表中第pos个位置插入node节点int LinkList_Insert(LinkList *list, int pos, LinkListNode *node);//获取链表第pos个位置节点LinkListNode *LinkList_Get(LinkList *list, int pos);//删除链表第pos个位置节点LinkListNode *LinkList_Delete(LinkList *list, int pos);#endif  //LinkList
  • LinkList.c
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "LinkList.h"typedef struct _tag_LinkList{    LinkListNode *header;    int length;}TLinkList;//创建链表LinkList *LinkList_Create() {    TLinkList *ret = NULL;    ret = (TLinkList *)malloc(sizeof(TLinkList));      if (ret == NULL)    {        printf("func LinkList_Create()  err\n");        return ret;    }    memset(ret, 0, sizeof(ret));    ret->length = 0;    ret->header = NULL;    return ret;}//销毁链表void LinkList_Destroy(LinkList *list){    if (list != NULL)    {        free(list);        return ;    }    return ;}//清空链表void LinkList_Clear(LinkList *list){    TLinkList *tlist = NULL;    if (list == NULL)    {        return;    }    tlist = (TLinkList *)list;    tlist->length = 0;    tlist->header= NULL;    return ;}//获取链表的长度int LinkList_Length(LinkList *list){    int ret;    TLinkList *tlist = NULL;    if (list == NULL)    {        ret = -1;        printf("func LinkList_Length()  err: %d\n", ret);        return ret;    }    tlist = (TLinkList *)list;    return tlist->length;}//向链表中第pos个位置插入node节点int LinkList_Insert(LinkList *list, int pos, LinkListNode *node){    int ret = 0, i = 0;    TLinkList *tlist = NULL;    LinkListNode *Current = NULL;    //①判断线性表是否合法    if (list == NULL || pos < 0 || node == NULL)    {        ret = -1;        printf("func LinkList_Insert() (list == NULL || pos < 0 || node == NULL) err:%d\n", ret);        return ret;    }    tlist = (TLinkList *)list;    //②判断插入位置是否合法    if (pos > tlist->length)    {        ret = -2;        printf("func LinList_Insert() (pos > tlist->length) err: %d\n", ret);        return ret;    }    //③插入节点    Current = &(tlist->header);    for (i = 0; i < pos&&(Current->next!=NULL); i++)  //找到pos位置的前一个节点    {        Current = Current->next;    }    node->next = Current->next;                      //用node节点连接pos位置的后一个节点    Current->next = node;                            //用pos位置前一个节点连接node的节点    //④线性表长度加一    tlist->length++;    return ret;}//获取链表第pos个位置节点LinkListNode *LinkList_Get(LinkList *list, int pos){    int i = 0, ret = 0;    TLinkList *tlist = NULL;    LinkListNode *Current = NULL;    //①判断线性表是否合法    if (list == NULL || pos < 0)    {        ret = -1;        printf("func LinkList_Get() (list == NULL || pos < 0) err: %d\n", ret);        return NULL;    }    tlist = (LinkList *)list;    //②判断插入位置是否合法    if (pos > tlist->length)    {        ret = -2;        printf("func LinkList_Get() (pos > tlist->length) err: %d\n",ret);        return NULL;    }    //③找到第pos位的节点    Current = &(tlist->header);    for (i = 0; i < pos && (Current->next != NULL); i++)    {        Current = Current->next;    }    return Current->next;}//删除链表第pos个位置节点LinkListNode *LinkList_Delete(LinkList *list, int pos){    int i = 0, ret = 0;    TLinkList *tlist = NULL;    LinkListNode *Current = NULL, *tmp = NULL;    //线性表是否合法    if (list == NULL || pos < 0)    {        ret = -1;        printf("func LinkList_Get() (list == NULL || pos < 0) err: %d\n",ret);        return NULL;    }    tlist = (TLinkList *)list;    //②判断插入位置是否合法    if (pos > tlist->length)    {        ret = -2;        printf("func LinkList_Get() (pos > tlist->length) err:%d\n",ret);        return NULL;    }    //③删除节点    Current = &(tlist->header);    for (i = 0; i < pos && (Current->next != NULL); i++)//找到pos位置的前一个节点    {        Current = Current->next;    }    tmp = Current->next;                                //保存pos位置节点    Current->next = tmp->next;                          //pos位置的前一个节点连接pos位置的后一个节点    //④线性表长度减一    tlist->length--;    return tmp;}
  • LinkList集成测试框架
#define _CRT_SECURE_NO_WARNINGS# include <stdio.h># include <stdlib.h># include <string.h># include "LinkList.h"typedef struct Teacher{    LinkListNode node;//(用于与其他节点产生联系)    int age;    char name[64];}Teacher;void main(){    int len = 0, ret = 0, i = 0;    LinkList *list = NULL;    Teacher t1, t2, t3, t4, t5;    t1.age = 11;    strcpy(t1.name, "t1");    t2.age = 22;    strcpy(t2.name, "t2");    t3.age = 33;    strcpy(t3.name, "t3");    t4.age = 44;    strcpy(t4.name, "t4");    t5.age = 55;    strcpy(t5.name, "t5");    list = LinkList_Create();                                        //创建链表    if (list == NULL)                                                //判断链表是创建成功    {        printf("func LinkList_Create()  err:\n");        return;    }    ret = LinkList_Insert(list, 0, (LinkListNode *)&t1);             //在插入节点    if (ret != 0)                                                    //判断节点是否成功插入    {        printf("func LinkList_Insert()  err: %d\n",ret);        return;    }    ret = LinkList_Insert(list, 1, (LinkListNode *)&t2);            //在插入节点    if (ret != 0)                                                   //判断节点是否成功插入    {        printf("func LinkList_Insert()  err: %d\n",ret);        return;    }    ret = LinkList_Insert(list, 2, (LinkListNode *)&t3);            //在插入节点    if (ret != 0)                                                   //判断节点是否成功插入    {        printf("func LinkList_Insert()  err: %d\n",ret);        return;    }    ret = LinkList_Insert(list, 3, (LinkListNode *)&t4);            //在插入节点    if (ret != 0)                                                   //判断节点是否成功插入    {        printf("func LinkList_Insert()  err: %d\n",ret);        return;    }    ret = LinkList_Insert(list, 4, (LinkListNode *)&t5);            //在插入节点    if (ret != 0)                                                   //判断节点是否成功插入    {        printf("func LinkList_Insert()  err: %d\n",ret);        return;    }    len = LinkList_Length(list);                                   //获取链表长度    printf("The length of list is:%d\n", len);    for(i=0;i<LinkList_Length(list);i++)                           //获取链表中的所有元素    {        Teacher *tmp = NULL;        tmp = (Teacher *)LinkList_Get(list, i);                    //获取链表第i个位置的节点        if (tmp == NULL)                                           //判断获取节点是否成功        {            printf("func LinkList_Get()  err\n");            return;        }        printf("tmp->name:%s,tmp->age:%d\n", tmp->name, tmp->age);    }    while (LinkList_Length(list))                                 //删除链表中的所有元素                     {        Teacher *tmp = NULL;        tmp = (Teacher *)LinkList_Delete(list, 0);                //删除链表第一个位置节点        if (tmp == NULL)                                          //判断删除节点是否成功        {            printf("func LinkList_Delete() err\n");            return;        }        printf("tmp->name:%s,tmp->age:%d\n", tmp->name, tmp->age);    }    len = LinkList_Length(list);                                 //获取链表长度    printf("The length of list is:%d\n", len);    LinkList_Clear(list);                                        //清空链表    LinkList_Destroy(list);                                      //销毁链表    return;}
原创粉丝点击