数据结构-链表(linkedList)-下篇(用C语言实现接口)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/NICE__FUTURE/article/details/81475078

回顾

在上篇(https://blog.csdn.net/NICE__FUTURE/article/details/81436165)中已经建立了简单链表的接口,所以这里将实现这些接口。

实现简单链表接口

  • 初始化链表

    • 链表头尾指针赋值为空
    • 链表长度初始化为0
//初始化链表,传入list进行初始化
void InitializeList(List *list)
{
    list->phead = list->ptail = NULL;
    list->total = 0;
}
  • 增加节点

    • 申请一块内存
    • 将要保存的数据写入节点
    • 将节点添加到链表末尾
//新增一个节点,传入list、新增节点的值
void AddNode(List *list, int value)
{
    //申请一块新内存,用于创建新节点
    Node *p = (Node*)malloc(sizeof(Node));
    if (p != NULL) {
        p->value = value;  //写数据
        p->plast = list->ptail;  //改节点地址
        p->pnext = NULL;
        //改链表地址
        if(list->phead == NULL) {   //无头节点时
            list->phead = list->ptail = p;
        } else {                    //存在头节点时
            list->ptail = (list->ptail)->pnext = p;
        }
    } else {
        exit(1);
    }
}
  • 插入节点

    • 让指针指向要插入的位置
    • 创建一段临时链表
    • 将用户数据存进临时链表
    • 将临时链表插入主链表
//插入一个或多个节点(一段链表), 传入插入位置前一个节点的索引
void InsertNode(List *list, int index)
{
    int i;
    Node *pindex = list->phead;

    //定位index指向的节点地址
    for (int i = 0; i < index; i++) {
        pindex = pindex->pnext;
    }

    //建一段临时链表
    List tempList;
    tempList.phead = tempList.ptail = NULL;

    addValue(&tempList, "插入");  //addValue是一个自定义函数,功能是从用户获得数据,存入链表中(链表作为参数传入),第二个参数是交互时显示给用户的部分提示文字

    //更改临时链表首尾存储的地址
    (tempList.phead)->plast = pindex;
    (tempList.ptail)->pnext = pindex->pnext;
    //更改插入位置两个节点存储的地址
    (pindex->pnext)->plast = tempList.ptail;
    pindex->pnext = tempList.phead;
}
  • 按值查找

    • 遍历链表
    • 每次进行数据(值)的比较
    • 将满足条件的节点地址放入一个指针数组(因为这个数组要返回,所以让它作为参数传入)
    • 将指针数组长度返回
//按值查找,传入list, 传入要查找的值和节点地址数组,结果将保存在传入的节点地址数组中,返回查找的个数
int SearchNodeValued(const List *list, int value, Node** pnodes)
{
    Node *p;
    int n = 0;

    //遍历链表进行比较
    for (p = list->phead; p; p = p->pnext) {
        if (p->value == value) {
            pnodes[n] = p;
            n++;
        }
    }

    return n;
}
  • 按区间查找

    • 要查找的(索引)区间作为参数传入
    • 将指针指向区间的开始处
    • 此后将节点地址放入指针数组(作为参数传入)
    • 指针指向区间结束位置为止
//按索引区间查找,传入list、序号区间、一个指针数组,运行时修改指针数组,数组由查找到的节点地址组成,序号越界等错误返回0,成功返回数组长度
int SearchNodeIndex(const List *list, int lowerNumber, int upperNumber, Node **pnodes)
{
    int i, cnt = 0;
    Node *p = list->phead;

    //如果越界或索引错误,返回0;
    if ( lowerNumber < 0 || upperNumber > (list->total)-1 || lowerNumber > upperNumber ) {
        return 0;
    }

    //找出上下限之间的地址存入数组
    for (i = 0; i < lowerNumber; i++) {
        p = p->pnext;
    }

    for (i = lowerNumber; i <= upperNumber; i++) {
        pnodes[cnt] = p;
        cnt++;
        p = p->pnext;
    }

    return cnt;
}
  • 按值删除

    • 按值查找所有符合的节点(前面有按值查找的接口)
    • 将符合的节点空间释放
    • 链表拼接,保持连续性
//删除所有值为value的节点,传入list, 要删除的值
int RmNodeValued(List *list, int value)
{
    Node* pnodes[list->total];
    int i, cnt = 0;

    cnt = SearchNodeValued(list, value, pnodes);  //获得所有值为value的节点地址
    for (i = 0; i < cnt; i++) {
        freeNode(list, pnodes[i]);  //自定义函数,功能是释放传入的节点,并且将传入的链表做拼接,保持连续性
    }

    return cnt;
}
  • 按区间删除

    • 按区间查找符合要求的节点(前面有按区间查找的接口)
    • 将节点的空间释放
    • 拼接链表
//按索引区间删除数据,传入list、索引的上下限
int RmNodeIndex(List *list, int lowerNumber, int upperNumber)
{
    Node* pnodes[list->total];
    int i, cnt = 0;

    //获得符合条件的节点地址,释放节点空间,拼接链表
    if (cnt = SearchNodeIndex(list, lowerNumber, upperNumber, pnodes)) {
        for (i = 0; i < cnt; i++) {
            freeNode(list, pnodes[i]);
        }
        return cnt;
    } else {
        printf("索引有误\n");
        return 0;
    }
}
  • 释放所有节点的空间

(虽然程序在运行完之后操作系统会将内存释放。但是还是养成及时释放用malloc申请来的空间的习惯)

  • 临时存储下一个节点的地址 (原因:释放了当前节点之后,下一个节点就没有途径访问了)
  • 释放当前节点
  • 将当前节点指向下一节点
//释放所有节点的空间
void FreeAllNodes(const List *list)
{
    Node *p = list->phead;
    Node *psave = NULL;

    while (p != NULL) {
        psave = p->pnext;  //保存下一节点地址
        free(p);           //释放当前节点
        p = psave;         //前进到下一节点
    }
}
  • 一点补充:
    • 上面因为数据区的数据少,所以没有单独将数据分开,实际上分开会好一些
    • 上面有的接口没有返回值就直接用的 void ,实际上可以返回一个值用于判断操作是否顺利完成。C语言没有布尔 boolean ( bool ) 类型,对此有两种解决办法:
      1. 如果编译器支持C99标准,可以 include <stdbool.h> 来使用 bool 类型
      2. 上面的不行的话,可以定义枚举类型 enum bool {true, false}; 来达到目的

使用接口

也就是说,实现接口之后需要写一个程序(驱动)来使用接口,测试下自己写的链表接口是否正确可用。

这有我写的一个简单测试我这个链表接口的代码:
GitHub: https://github.com/NICE-FUTURE/WorkSpace/tree/master/cprogram/linkedList

展开阅读全文

数据结构链表(C语言

09-26

#includern#includerntypedef struct nodern int data;rn struct node *next;rnNODE;rn rn void *InitList(NODE *L)rn L=(NODE *)malloc(sizeof(NODE));rn L->next=NULL;rn return 0;rn rnrnrn void *creat(NODE *L)rn int m,i; NODE *q,*p ;rn printf("qing shu ru shu mu:");rn scanf("%d",&m);rn printf("qing shu ru shu zi:");rn q=(NODE *)malloc(sizeof(NODE));rn q=L;rn for(i=0;idata);rn p->next=NULL;rn q->next=p;rn q=p;rnprintf("wan cheng\n");rn return 0;rnrnrnrn void *ListInsert(NODE *L)rn int i,e,j; NODE *p,*s;rn printf("Now you will push a number into the list !\n");rn printf("Where do you want to push the number,pleast input the xuhao:");rn scanf("%d",&i);rn printf("Now the number will push before %d! \n",i);rn printf("Please input your number:");rn scanf("%d",&e); printf("\n");rn p=L; j=0;rn while(p!=NULL&&jnext; ++j;rn if(p==NULL||j>i-1) return 0;rn s=(NODE *)malloc(sizeof(NODE));rn s->data=e; s->next=p->next;rn p->next=s;rn printf("The %d have been push into the list! \n",e);rn return 0;rnrnrn void *ListDel(NODE *L)rn int i,j; NODE *p,*q;rn printf("Now you will delete a number from the list! \n");rn printf("Please input the number's xuhao :");rn scanf("%d",&i); printf("\n");rn p=L; j=0;rn while(p->next!=NULL&&jnext; ++j;rn if(p->next==NULL||j>i-1) return 0;rn q=p->next; p->next=q->next;rn printf("The %d is delete successfully!\n",q->data);rn free(q);rn return 0;rnrnrnrn void PrintList(NODE *L)rn NODE *p;rn p=(NODE *)malloc(sizeof(NODE));rn p=L->next;rn while(p!=NULL)rn printf("%5d",p->data);rn p=p->next;rnrnrnrnrn void main()rn NODE *T; int n=0;rn printf("1.InitList 2.ListInsert 3.ListDel 4.PrintfList 5.Exit \n");rn while(n!=5)rn printf("Please choose the gongneng:");rn scanf("%d",&n);rn switch(n)rn case 1:rn InitList(T);rn creat(T);printf("\n");rn break;rn case 2:rn ListInsert(T);rn break;rn case 3:rn ListDel(T);rn break;rn case 4:rn PrintList(T); printf("\n");rn break;rn case 5:rn break;rn rnrn 论坛

没有更多推荐了,返回首页