C语言实现顺序链表

1 概念:

指用一个连续的地址来存储数据元素。结构类似数组

2 设计与实现:

a 设计要素:

1)插入元素算法
  • 判断线性表是否合法
  • 判断插入位置是否合法
  • 把最后一个元素到插入位置的元素后移一个位置
  • 将新元素插入后线性表长度加1

b 实现代码:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#include "seqlist.h"

typedef struct _tag_SeqList
{
    int capacity;
    int length;
    unsigned int *node; //unsigned int array[capacity]
}TSeqList;



SeqList* SeqList_Create(int capacity)//创建链表
{
    TSeqList *ret = NULL;
    if (capacity < 0)
    {
        return NULL;
    }
    ret = (TSeqList *)malloc(sizeof(TSeqList) + sizeof(unsigned int )*capacity );
    if (ret == NULL)
    {
        return NULL;
    }
    memset(ret, 0, sizeof(sizeof(TSeqList)) + sizeof(unsigned int )*capacity );
    ret->node = (unsigned int *)(ret +1); //ret向后跳sizeof(TSeqList)
    ret->capacity = capacity;
    ret->length = 0;
    return ret;
}

void SeqList_Destroy(SeqList* list)//删除链表
{
    if (list == NULL)
    {
        return ;
    }
    free(list);
    return ;
}

//链表清零 。。。长度为零
void SeqList_Clear(SeqList* list)
{
    TSeqList *tList = NULL; 

    if (list == NULL)
    {
        return ;
    }
    tList  = (TSeqList *)list;
    tList->length = 0;
    return ;
}

int SeqList_Length(SeqList* list)//返回链表长度
{
    TSeqList *tList = NULL; 
    tList = (TSeqList *)list;
    if (list == NULL)
    {
        return -1;
    }

    return tList->length;
}

//线性表的容量和线性表长度是不一样的
int SeqList_Capacity(SeqList* list)//
{
    TSeqList *tList = NULL; 
    tList = (TSeqList *)list;
    if (list == NULL)
    {
        return -1;
    }

    return tList->capacity;
}

int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)//插入元素
{
    int i = 0;
    TSeqList *tList = NULL; 
    tList  = (TSeqList *)list;

    if (list == NULL || node == NULL) 
    {
        return -1;
    }

    //查看是不是满了
    if (tList->length >= tList->capacity)
    {
        return -2;
    }

    //位置错误判断
    if (pos<0 || pos>=tList->capacity)
    {
        return -3;
    }

    //优化的容错。。。
    if (pos >=tList->length)
    {
        pos = tList->length;
    }

    //插入算法
    //从pos位置处开始,把数组后面的元素依此后移
    for(i=tList->length; i>pos; i--)
    {
        //把前的元素往后移
        tList->node[i] = tList->node[i-1];
    }
    //循环跳出以后,pos正好是,要出入的位置
    tList->node[pos] = (unsigned int)node;
    tList->length ++;
    return 0;
}

SeqListNode* SeqList_Get(SeqList* list, int pos)//根据位置返回链表中的元素
{

    SeqListNode *ret = NULL;
    TSeqList *tList = NULL;
    tList = (TSeqList *)list;
    if (list == NULL || pos<0 || pos>=tList->length)
    {
        return NULL;
    }
    ret = (SeqListNode*)tList->node[pos];
    return ret;
}

SeqListNode* SeqList_Delete(SeqList* list, int pos)//删除一个位置上的元素
{
    int                 i;
    TSeqList                *tList = NULL;
    SeqListNode         *ret = NULL; 
    tList = (TSeqList *)list;

    if (list==NULL || pos<0 || pos>=tList->length)
    {
        return NULL;
    }

    //赋给a3之前,要把a3元素缓存下来
    ret = (SeqListNode *)tList->node[pos];
    //删除算法
    for (i=pos+1; ilength; i++)
    {
        tList->node[i-1] = tList->node[i];
    }
    tList->length --;

    return ret;
}

3、优点和缺点

  • 优点:
    无需一次性定制链表的容量
    插入和删除操作无需移动数据元素
  • 缺点:
    一次分配了全部内存,内存消耗较大
    数据元素必须保存后继元素的位置信息
    获取指定数据的元素操作需要顺序访问之前的元素

你可能感兴趣的:(数据结构与算法)