c/c++常用算法(2) -- 数据结构(线性表的链式存储)

一、线性表的链式存储结构


      链式存储:用一组任意的存储单元存储线性表中的数据元素。用这种方法存储的线性表简称线性链表

      存储链表中结点的一组任意的存储单元可以是连续的,也可以是不连续的,甚至是零散分布在内存中的任意位置上的。

      链表中结点的逻辑顺序和物理顺序不一定相同。

      为了正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其直接后继结点的地址(或位置),称为指针(pointer)或链(link),这两部分组成了链表中的结点结构,如图2-2所示。


data :数据域,存放结点的值

                       next:指针域,存放结点的直接后继的地址


      表是通过每个结点的指针域将线性表的n个结点按其逻辑次序链接在一起的。

      每一个结只包含一个指针域的链表,称为单链表。

      为操作方便,总是在链表的第一个结点之前附设一个头结点(头指针)head指向第一个结点。头结点的数据域可以不存储任何信息(或链表长度等信息)。


二、结点描述与实现


1 .描述


      C语言中用带指针的结构体类型来描述

typedef  struct  Lnode
{   ElemType  data;     /*数据域,保存结点的值 */
    struct   Lnode  *next;      /*指针域*/
}LNode;        /*结点的类型 */

2.实现


      结点是通过动态分配和释放来的实现,即需要时分配,不需要时释放。实现时是分别使用C语言提供的标准函数:malloc(),realloc(),sizeof(),free() 。


      动态分配   p=(LNode*)malloc(sizeof(LNode));

      函数malloc分配了一个类型为LNode的结点变量的空间,并将其首地址放入指针变量p中。


      动态释放  free(p);

      系统回收由指针变量p所指向的内存区。P必须是最近一次调用malloc函数时的返回值。


3.代码:


List.h

#ifndef __CHelloWorld__List__
#define __CHelloWorld__List__

#include <iostream>
using namespace std;

typedef struct
{
    char key[10];   //结点的关键字
    char name[20];
    int age;
}Data;              //结点类型

typedef struct Node     //定义链表结构
{
    Data nodeData;
    struct Node *nextNode;
}CLType;

class List
{
public:
    CLType *CLAddEnd(CLType* head,Data nodeData);   //追加结点(链表尾增加结点)
    CLType *CLAddFirst(CLType* head,Data nodeData); //插入头结点
    CLType *CLFindNode(CLType* head,char *key);     //查找结点
    CLType *CLInsetNode(CLType* head,char *findkey,Data nodeData);//插入结点
    int CLDeleteNode(CLType* head,char *key);       //删除结点
    int CLLength(CLType* head);                     //计算链表长度
    void CLAllNode(CLType *head);                   //遍历链表
};

#endif /* defined(__CHelloWorld__List__) */
List.cpp

#include "List.h"

CLType *List::CLAddEnd(CLType *head, Data nodeData)
{
    CLType *node;
    CLType *htemp;
    if (!(node = (CLType*)malloc(sizeof(CLType))))
    {
        cout<<"申请内存失败!"<<endl;
        return NULL;
    }
    else
    {
        node->nodeData = nodeData;
        node->nextNode = NULL;
        if (head == NULL)
        {
            head = node;
            return head;
        }
        htemp = head;
        while (htemp->nextNode != NULL)
        {
            htemp = htemp->nextNode;
        }
        htemp->nextNode = node;
        return head;
    }
}

CLType *List::CLAddFirst(CLType *head, Data nodeData)
{
    CLType *node;
    if (!(node = (CLType*)malloc(sizeof(CLType))))
    {
        cout<<"申请内存失败!"<<endl;
        return NULL;
    }
    else
    {
        node->nodeData = nodeData;
        node->nextNode = head;
        head = node;
        return head;
    }
}

CLType *List::CLFindNode(CLType *head, char *key)
{
    CLType *htemp;
    htemp = head;
    while (htemp)
    {
        if (strcmp(htemp->nodeData.key, key) == 0)
        {
            return htemp;
        }
        htemp = htemp->nextNode;
    }
    return NULL;
}

CLType *List::CLInsetNode(CLType *head ,char *findkey, Data nodeData)
{
    CLType *node,*nodetemp;
    if (!(node = (CLType*)malloc(sizeof(CLType))))
    {
        cout<<"申请内存失败!"<<endl;
        return NULL;
    }
    node->nodeData = nodeData;
    nodetemp = CLFindNode(head, findkey);
    if (nodetemp)
    {
        node->nextNode = nodetemp->nextNode;
        nodetemp->nextNode = node;
    }
    else
    {
        cout<<"未找到正确的插入位置!"<<endl;
        free(node);
    }
    return head;
}

int List::CLDeleteNode(CLType *head, char *key)
{
    CLType *node,*htemp;
    htemp = head;
    node = head;
    while (htemp)
    {
        if (strcmp(htemp->nodeData.key, key) == 0)
        {
            node->nextNode = htemp->nextNode;
            free(htemp);
            return 1;
        }
        else
        {
            node = htemp;
            htemp = htemp->nextNode;
        }
    }
    return 0;
}

int List::CLLength(CLType *head)
{
    CLType *htemp;
    int Len = 0;
    htemp = head;
    while (htemp)
    {
        Len++;
        htemp = htemp->nextNode;
    }
    return Len;
}

void List::CLAllNode(CLType *head)
{
    CLType *htemp;
    Data nodeData;
    htemp = head;
    printf("当前链共有%d个结点。链表所有数据如下:\n",CLLength(head));
    while (htemp)
    {
        nodeData = htemp->nodeData;
        printf("结点(%s,%s,%d)\n",nodeData.key,nodeData.name,nodeData.age);
        htemp = htemp->nextNode;
    }
}
main.cpp

#include <iostream>
#include "List.h"
using namespace std;

int main(int argc, const char * argv[])
{
    CLType *node,*head = NULL;
    Data nodeData;
    char key[10],findkey[10];
    List *mylist = new List();
    std::cout << "链表操作演示\n";
    do
    {
        std::cout << "输入添加的结点(学号 姓名 年龄):";
        fflush(stdin);  //清空输入缓冲区
        scanf("%s",nodeData.key);
        if (strcmp(nodeData.key, "0") == 0)   //年龄不能为0
        {
          break;
        }
        else
        {
            scanf("%s%d",nodeData.name,&nodeData.age);
            head = mylist->CLAddEnd(head,nodeData);
        }
    } while (1);
    
    mylist->CLAllNode(head);
    
    std::cout << "\n要插入结点:";
    scanf("%s",&findkey);
    std::cout << "输入插入结点的数据(学号 姓名 年龄):\n";
    scanf("%s%s%d",nodeData.key,nodeData.name,&nodeData.age);
    head = mylist->CLInsetNode(head, findkey, nodeData);
    mylist->CLAllNode(head);
    
    std::cout << "\n要删除结点:";
    scanf("%s",key);
    mylist->CLDeleteNode(head, key);
    mylist->CLAllNode(head);
    
    std::cout << "\n演示在链表中查找,输入查找关键字:";
    fflush(stdin);
    scanf("%s",key);
    node = mylist->CLFindNode(head, key);
    if (node)
    {
        nodeData = node->nodeData;
        scanf("关键字%s对应的结点为(%s,%s,%d)",key,nodeData.key,nodeData.name,&nodeData.age);
    }
    else
    {
        printf("在链表中未找到关键字为%s的结点!\n",key);
    }
    
    delete mylist;
    // insert code here...
   // std::cout << "Hello, World!\n";
    return 0;
}

演示效果图:


            


参考书籍:《C/C++常用算法手册》  《数据结构-清华大学严蔚敏》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热血枫叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值