传统的链表不能实现数据和链表的分离,一旦数据改变则链表就不能用了,就要重新开发。

如上说示:外层是Teacher,里面小的是node.

#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_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); int LinkList_Insert(LinkList* list, LinkListNode* node, int pos); LinkListNode* LinkList_Get(LinkList* list, int pos); LinkListNode* LinkList_Delete(LinkList* list, int pos); #endif
#define  _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "linklist.h" typedef struct _tag_LinkList//这个链表的上下文信息,类似于handle.这里面是链表的头结点和链表的长度。
{
LinkListNode header;
int length;
}TLinkList; LinkList* LinkList_Create() //O(1)
{
TLinkList *tmp = NULL; tmp = (TLinkList *)malloc(sizeof(TLinkList));
if (tmp == NULL)
{
printf("func LinkList_Create() err \n");
return NULL;
}
memset(tmp, , sizeof(TLinkList));
tmp->length = ;
tmp->header.next = NULL; //
return tmp;
} void LinkList_Destroy(LinkList* list) //O(1)
{
if (list == NULL)
{
return ;
}
free(list);//只把上下文信息释放。因为加进去的Teacher对象是局部的,main函数执行完后会自动释放,所以这里不用手动释放。
return ;
} void LinkList_Clear(LinkList* list) //O(1)
{
TLinkList *tList = NULL;
tList = (TLinkList *)list;
if (tList == NULL)
{
return ;
}
tList->header.next = NULL;
tList->length = ; return ;
} int LinkList_Length(LinkList* list) //O(1)
{
TLinkList *tList = NULL;
tList = (TLinkList *)list;
if (tList == NULL)
{
return -;
}
return tList->length;
} int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) //在pos位置插入节点,先连接后面的再连接前面的。
{
int i = ;
LinkListNode *current = NULL;
TLinkList *tList = NULL;
if (list==NULL || node==NULL || pos<)//node为新节点
{
return -;
}
tList = (TLinkList *)list; current = &(tList->header);//节点要取地址给指针
for (i=; i<pos; i++)//链表节点序号从0开始
{
current = current->next;//current为pos位置前面的节点
}
//先连接后面节点在连接前面节点
node->next = current->next; //前面的链表 连接 新结点
current->next = node; tList->length ++;
return ;
} LinkListNode* LinkList_Get(LinkList* list, int pos) //O(n)
{
int i = ;
LinkListNode *current = NULL;
TLinkList *tList = NULL; tList = (TLinkList *)list; if (list==NULL || pos<)
{
return NULL;
} current = &(tList->header); //赋值指针变量初始化
for (i=; i<pos; i++)
{
current = current->next;
}
return current->next;
} LinkListNode* LinkList_Delete(LinkList* list, int pos) //O(n)
{
int i = ;
LinkListNode *current = NULL;
LinkListNode *ret = NULL;
TLinkList *tList = NULL; tList = (TLinkList *)list;
if (list==NULL || pos<)
{
return NULL;
} current = &(tList->header);
for (i=; i<pos; i++)
{
current = current->next;
}
ret = current->next; //缓存要删除的结点 current->next = ret->next; tList->length --; return ret;
}
#define  _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "linklist.h" /*
typedef struct _Node
{
struct _Node *next;
}Node; typedef struct _Teacher1
{
char name[32];
int age ;
Node node;
}Teacher1; typedef struct _Teacher2
{
Node node;
char name[32];
int age ; }Teacher2; Teacher2 t2;
*/ typedef struct _Teacher
{
LinkListNode node; //偏移量:从node元素找到Teacher的地址。写到上面则node的内存首地址和Teacher对象的内存首地址重叠了。
char name[];
int age ;
}Teacher; void main()
{
LinkList *list = NULL;
int i = ; Teacher t1, t2, t3, t4, t5, t6;//main函数结束这几个变量释放
t1.age = ;
t2.age = ;
t3.age = ;
t4.age = ;
t5.age = ;
t6.age = ; list = LinkList_Create(); //思考1: 业务节点 和 链表算法是如何分离
//思考2: 业务节点的生命周期 归谁管... //插入元素
LinkList_Insert(list, (LinkListNode *)&t1, );//t1地址和node地址是重叠的
LinkList_Insert(list, (LinkListNode *)&t2, );
LinkList_Insert(list, (LinkListNode *)&t3, );
LinkList_Insert(list, (LinkListNode *)&t4, );
LinkList_Insert(list, (LinkListNode *)&t5, );
LinkList_Insert(list, (LinkListNode *)&t6, ); //遍历链表
for (i=; i<LinkList_Length(list); i++)
{
Teacher *tmp = (Teacher *)LinkList_Get(list, i);
if (tmp == NULL)
{
return ;
}
printf("age:%d \n", tmp->age);
} //删除链表结点
while (LinkList_Length(list) > )
{
Teacher *tmp = (Teacher *)LinkList_Delete(list, );
if (tmp == NULL)
{
return ;
}
printf("age:%d \n", tmp->age);
} LinkList_Destroy(list); printf("hello...\n");
system("pause");
return ;
}

C_数据结构_链表的链式实现的更多相关文章

  1. c_数据结构_链表

    #include<stdio.h> #include<stdlib.h> #define ERROR 0 #define OK 1 #define OVERFLOW -2 ty ...

  2. C语言实现链表(链式存储结构)

    链表(链式存储结构)及创建 链表,别名链式存储结构或单链表,用于存储逻辑关系为 "一对一" 的数据.与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其 ...

  3. javascript实现数据结构:线性表--线性链表(链式存储结构)

    上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...

  4. C++实现链队类——合肥工业大学数据结构实验5:链式队列

    实验5 5.1 实验目的 熟练掌握队列的顺序链式存储结构. 熟练掌握队列的有关算法设计,并在链队列上实现. 根据具体给定的需求,合理设计并实现相关结构和算法. 5.2 实验要求 5.2.1链队列实验要 ...

  5. c_数据结构_队的实现

    # 链式存储#include<stdio.h> #include<stdlib.h> #define STACK_INIT_SIZE 100//存储空间初始分配量 #defin ...

  6. C_数据结构_链式二叉树

    # include <stdio.h> # include <malloc.h> struct BTNode { int data; struct BTNode * pLchi ...

  7. 数据结构-线性表的链式存储相关算法(C语言实现)

    链表的简单介绍 为什么需要线性链表 当然是为了克服顺序表的缺点,在顺序表中,做插入和删除操作时,需要大量的移动元素,导致效率下降. 线性链表的分类 按照链接方式: 按照实现角度: 线性链表的创建和简单 ...

  8. c_数据结构_图_邻接表

    课程设计------邻接表 图的遍历实现课程设计:https://files.cnblogs.com/files/Vera-y/图的遍历_课程设计.zip #include<stdio.h> ...

  9. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_04 数据结构_4_数据结构_链表

    查询慢,增删快. 绿色代表一条链 红色是另外一条链 .查询是从头开始查所以慢. 在300和55之间添加一个元素

随机推荐

  1. (四)学习MVC之修改个人资料和身份验证登陆

    1.修改资料不用建立模型,直接在UserControl.cs添加 ChangeInfo(): #region 修改用户资料 [UserAuthorize] public ActionResult Ch ...

  2. qtp不识别树结构中的点击事件

    qtp不识别树结构中的点击事件,未生成该点击事件的脚本,解决办法: 1.未生成点击"auto分类c1"的脚本 2.点击1.对象库-2.添加对象库-3.选中对象-点击OK,即将该对象 ...

  3. Linux 多线程编程--线程退出

    今天分析项目中进程中虚存一直增长问题,运行10个小时虚存涨到121G ,RSS占用为16G 非常恐怖. Valgrind测试无内存泄漏. 内存32G 64bit系统信息如下: Linux线程使用方式是 ...

  4. Flume 与Kafka区别

    今天开会讨论日志处理为什么要同时使用Flume和Kafka,是否可以只用Kafka 不使用Flume?当时想到的就只用Flume的接口多,不管是输入接口(socket 和 文件)以及输出接口(Kafk ...

  5. 3D魔方游戏

    初学OpenGL时做的小程序,涉及到了OpenGL的大部分基本内容,如视图模型变换.色彩.纹理贴图.材质.光照.显示列表.选择等 三阶魔方有3×3×3个方块组成,每个方块的类当中都有一个4×4的矩阵, ...

  6. 【转】Linux 技巧: Bash 参数和参数扩展

    重点看下清单7 现在,很多 Linux® 和 UNIX® 系统上都有 bash shell,它是 Linux 上常见的默认 shell.通过本文,您将了解到如何在 bash 脚本中处理参数和选项,以及 ...

  7. DateTime和DateTime2

    1.与ANSI和ISO8601标准的一致性不同 datetime不符合该标准,datetime2符合该标准.对于新的应用,尽量使用符合标准的类型. 2.表示范围的不同 datetime:1753-01 ...

  8. CentOS 6.5 安装配置VSFTP

    1.下载安装VSFTP 首先查看当前系统是否已经安装VSFTP,若未安装则使用yum安装. chkconfig --list | grep vsftpd #查看是否安装 yum install vsf ...

  9. HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436 树状数组做法<猛戳> Splay tree的经典题目,有删除和移动操作.首先要离散化 ...

  10. 【转】 hive简介,安装 配置常见问题和例子

    原文来自:  http://blog.csdn.net/zhumin726/article/details/8027802 1 HIVE概述 Hive是基于Hadoop的一个数据仓库工具,可以将结构化 ...