有的时候,处于内存中的数据并不是连续的。那么这时候,我们就需要在数据结构中添加一个属性,这个属性会记录下面一个数据的地址。有了这个地址之后,所有的数据就像一条链子一样串起来了,那么这个地址属性就起到了穿线连结的作用。

相比较普通的线性结构,链表结构的优势是什么呢?我们可以总结一下:

(1)单个节点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小

(2)节点的删除非常方便,不需要像线性结构那样移动剩下的数据

(3)节点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的访问效率低于线性表

那么在实际应用中,链表是怎么设计的呢?我们可以以int数据类型作为基础,设计一个简单的int链表:

(1)设计链表的数据结构

typedef struct _LINK_NODE
{
int data;
struct _LINK_NODE* next;
}LINK_NODE;

(2)创建链表

LINK_NODE* alloca_node(int value)
{
LINK_NODE* pLinkNode = NULL;
pLinkNode = (LINK_NODE*)malloc(sizeof(LINK_NODE)); pLinkNode->data = value;
pLinkNode->next = NULL;
return pLinkNode;
}

(3)删除链表

void delete_node(LINK_NODE** pNode)
{
LINK_NODE** pNext;
if(NULL == pNode || NULL == *pNode)
return ; pNext = &(*pNode)->next;
free(*pNode);
delete_node(pNext);
}

(4)链表插入数据

STATUS _add_data(LINK_NODE** pNode, LINK_NODE* pDataNode)
{
if(NULL == *pNode){
*pNode = pDataNode;
return TRUE;
} return _add_data(&(*pNode)->next, pDataNode);
} STATUS add_data(const LINK_NODE** pNode, int value)
{
LINK_NODE* pDataNode;
if(NULL == *pNode)
return FALSE; pDataNode = alloca_node(value);
assert(NULL != pDataNode);
return _add_data((LINK_NODE**)pNode, pDataNode);
}

(5)删除数据

STATUS _delete_data(LINK_NODE** pNode, int value)
{
LINK_NODE* pLinkNode;
if(NULL == (*pNode)->next)
return FALSE; pLinkNode = (*pNode)->next;
if(value == pLinkNode->data){
(*pNode)->next = pLinkNode->next;
free(pLinkNode);
return TRUE;
}else{
return _delete_data(&(*pNode)->next, value);
}
} STATUS delete_data(LINK_NODE** pNode, int value)
{
LINK_NODE* pLinkNode;
if(NULL == pNode || NULL == *pNode)
return FALSE; if(value == (*pNode)->data){
pLinkNode = *pNode;
*pNode = pLinkNode->next;
free(pLinkNode);
return TRUE;
} return _delete_data(pNode, value);
}

(6)查找数据

LINK_NODE* find_data(const LINK_NODE* pLinkNode, int value)
{
if(NULL == pLinkNode)
return NULL; if(value == pLinkNode->data)
return (LINK_NODE*)pLinkNode; return find_data(pLinkNode->next, value);
}

(7)打印数据

void print_node(const LINK_NODE* pLinkNode)
{
if(pLinkNode){
printf("%d\n", pLinkNode->data);
print_node(pLinkNode->next);
}
}

(8)统计数据

int count_node(const LINK_NODE* pLinkNode)
{
if(NULL == pLinkNode)
return 0; return 1 + count_node(pLinkNode->next);
}

【预告: 下一篇博客介绍双向链表

c++(单向链表)的更多相关文章

  1. Reverse Linked List II 单向链表逆序(部分逆序)

    0 问题描述 原题点击这里. 将单向链表第m个位置到第n个位置倒序连接.例如, 原链表:1->2->3->4->5, m=2, n =4 新链表:1->4->3-& ...

  2. 【编程题目】输入一个单向链表,输出该链表中倒数第 k 个结点

    第 13 题(链表):题目:输入一个单向链表,输出该链表中倒数第 k 个结点.链表的倒数第 0 个结点为链表的尾指针.链表结点定义如下: struct ListNode {int m_nKey;Lis ...

  3. 输出单向链表中倒数第k个结点

    描述 输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第0个结点为链表的尾指针. 链表结点定义如下: struct ListNode { int       m_nKey; ListNode* ...

  4. Linus:利用二级指针删除单向链表

    Linus大神在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level codi ...

  5. 【转】Linus:利用二级指针删除单向链表

    原文作者:陈皓 原文链接:http://coolshell.cn/articles/8990.html 感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多, ...

  6. C语言实现单向链表及其各种排序(含快排,选择,插入,冒泡)

    #include<stdio.h> #include<malloc.h> #define LEN sizeof(struct Student) struct Student / ...

  7. 数据结构——Java实现单向链表

    结点类: /** * @author zhengbinMac * 一个OnelinkNode类的对象只表示链表中的一个结点,通过成员变量next的自引用方式实现线性表中各数据元素的逻辑关系. */ p ...

  8. 输入一个单向链表,输出该链表中倒数第K个结点

    输入一个单向链表,输出该链表中倒数第K个结点,具体实现如下: #include <iostream> using namespace std; struct LinkNode { publ ...

  9. 单向链表JAVA代码

        //单向链表类 publicclassLinkList{       //结点类     publicclassNode{         publicObject data;         ...

  10. C++ 单向链表反转

    单向链表反转,一道常见的面试题,动手实现下. #include "stdafx.h" #include <stdlib.h> struct Node{ int data ...

随机推荐

  1. bzoj 1486: [HNOI2009]最小圈

    Description Input Output Sample Input 4 5 1 2 5 2 3 5 3 1 5 2 4 3 4 1 3 Sample Output 3.66666667 HIN ...

  2. free 命令详解

    作用:显示当前系统未使用的和已使用的内存数目,还可以显示被内核使用的内存缓冲区 选项: -b 以byte为单位显示内存使用情况 -k 以kb 为单位显示内存使用情况 -m 以mb 为单位显示内存使用情 ...

  3. rpm 命令详解

    参考:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/10/08/2203153.html rpm是由红帽公司开发的软件包管理方式,使用r ...

  4. Windows zip安装MySQL

    1. mysqld初始化时my.ini的第二个默认位置是%windir%/my.ini rem 1.查看此变量对应的目录,在此目录下编辑 my.ini,mysqld会自动找到 echo %WINDIR ...

  5. go 1.9 Beta 1

    语言变化:增加了类型别名 To find out what has changed in Go 1.9, read the draft release notes: https://tip.golan ...

  6. 准确率(Accuracy), 精确率(Precision), 召回率(Recall)和F1-Measure(对于二分类问题)

    首先我们可以计算准确率(accuracy),其定义是: 对于给定的测试数据集,分类器正确分类的样本数与总样本数之比.也就是损失函数是0-1损失时测试数据集上的准确率. 下面在介绍时使用一下例子: 一个 ...

  7. crontabs linux定时任务功能安装

    crontab命令常见于Unix和Linux的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于"crontab"文件中,以供之后读取和执行.通常 ...

  8. spring项目读取配置文件

    Spring项目在运用中读取配置文件有两种方式: 通过项目的配置文件读取 在spring-context.xml里面加入以下代码 在运用到的类里面加入 @Value("#{configPro ...

  9. Use Zabbix Monitor Find ‘DBCC CheckDB’ Problem

    下面是修改前后的对比截图: 如下图: 下图是确定问题并修改后对比图,左边圈是修改前,右边圈是修改后对比截图:当看到周期性的性能指数,一般是计划性任务引起:通过DMV视图,找到引起等待的原因检查数据库完 ...

  10. Robot Framework学习笔记(十一)------ 分层设计

    以百度搜索为例,如果我们需要写5个不同关键字搜索的用例.如果没有分层的思想,那么我们需要写5个用例,并且每个用例都需要重复写打开浏览器.输入关键字.点击按钮.关闭浏览器的步骤.如果使用Robot Fr ...