新人,c语言链表视频教程,想递减排序链表中数据,调试时显示在图中,交换两节点

C语言的通用链表
在操作中, 往往是使用C语言, 但C使用起来极为痛苦, 不像C++有方便的STL模板库使用。
linux内核中,有一套非常神奇的通用链表结构,能够方便的使用,管理各种类型的数据,我们今天就来研究一下,内核中的C数据结构。
本文参考:【深入分析
内核链表】
首先,我们的目标是构建一个循环双链表结构,为何是双链表,还要循环,当然是从易用性考虑了,双链表能够方便的得知自己的上一个元素,在内核中管理数据更为方便。
其一般结构大概是这样:
首先定义一个list_node结构,用来保存链表节点信息:
* @brief 链表节点结构
typedef struct _list_node
struct _list_node
struct _list_node
然后用一个存放数据的结构,比如我们要用int型的链表,如下定义:
* @brief 数据存放结构
typedef struct _Int_List
这和我们传统的链表实现思路好像不大一样,我们经典的C语言链表当然是在链表中保存数据:
* @brief 链表节点结构
typedef ElementT
typedef struct _list_node
struct _list_node
struct _list_node
但这样的实现必然会造成链表结构被反复定义,难以实现泛型。另外一种思路可能是将ElementType实现成void*指针,然后在使用时进行强制类型转换,但这样必然会带来反复的类型转换,而且其使用相对不便。
这时要出问题了,如果数据在外层,链表在里层,那么如何从链表找到数据呢?
offsetof宏和container_of宏
为了实现从内层元素找外层元素的功能,我们需要用到这两个系统宏,一眼看上去很复杂,但实际上并不难理解。
* @brief 确定当前成员变量,在结构体中偏移量的宏
#ifndef offsetof
#define offsetof(type, member) ((size_t) &((type*)0)-&member)
* @brief 根据成员变量,找包含他的结构体指针
#ifndef container_of
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)-&member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
这两个宏较为复杂,首先是offsetof宏,这个宏用0号指针去寻找成员变量,我们试想,如何是普通的一个结构体,C编译器如何查找其一个成员呢?
* @brief 数据存放结构
typedef struct _Int_List
假设我们用Int_List A语句,实例化一个结构体,然后取到了A的地址0x
那么node的起始地址是不是也是0x
data的起始地址是不是0x+data的偏移量?
那么如何我想求data的偏移量,不就是如下的代码么:
(&A)-&data - (&A);
如果A的地址为0时,那么也就不用减了,就是我们宏定义中的用法。
而container_of宏也是采用类似的思路,既然找到了当前list_node成员的偏移量,那么减去偏移量,便是外层包围着的结构体的起始地址。
那好,这样我们就能实现这个链表了,但其实也不用这样费事,还有简单的办法,那就是让我们的被包含的list_node成员结构,处于我们数据存储结构的第一个位置,那么其地址就是包围其结构的地址,直接类型转换即可。
这种思路实际上也被用于C语言的继承机制的实现。
Github项目
到此,我们已经讲解了通用链表的实现思路,大家可以尝试自己实现一个独特的通用链表,具体内容就不一一赘述,我将完整的工程已经发布到了Github上面,欢迎大家前来fork测试。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'扫二维码下载作业帮
1.75亿学生的选择
下载作业帮安装包
扫二维码下载作业帮
1.75亿学生的选择
C语言的链表问题1. 已知链表结点定义语句为“struct node{ struct node *};”, 在下图所示的链表中,head为头指针,p0指向一个新建结点,则将p0按num域降序的规律插入到链表中的语句是(
p0->next =head-> head->next =p0;
head->next= p0-> p0 = head->
head->next=p0; p0->next=NULL;
head->next=3;p0->next=7;
这个怎么看。。。完全不懂,有详细解释的么
扫二维码下载作业帮
1.75亿学生的选择
A是对的。这个图片说明,应该这样操作p0->next = head->head->next = p0;
为您推荐:
扫描下载二维码刚看了单向链表的排序,有个地方不懂,代码和问题在下,求解答_c语言吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:514,467贴子:
刚看了单向链表的排序,有个地方不懂,代码和问题在下,求解答收藏
struct student *InsertSort(struct student *head)
struct student * /*为原链表剩下用于直接插入排序的节点头指针*/
struct student *t; /*临时指针变量:插入节点*/
struct student *p; /*临时指针变量*/
struct student *q; /*临时指针变量*/
first = head-& /*原链表剩下用于直接插入排序的节点链表:可根据图12来理解。*/
head-&next = NULL; /*只含有一个节点的链表的有序链表:可根据图11来理解。*/
while (first != NULL) /*遍历剩下无序的链表*/
/*注意:这里for语句就是体现直接插入排序思想的地方*/
for (t = first, q = ((q! = NULL) && (q-&num & t-&num)); p = q, q = q-&next); /*无序节点在有序链表中找插入的位置*/
/*退出for循环,就是找到了插入的位置*/
/*注意:按道理来说,这句话可以放到下面注释了的那个位置也应该对的,但是就是不能。原因:你若理解了上面的第3条,就知道了。*/
first = first-& /*无序链表中的节点离开,以便它插入到有序链表中。*/
if (q == head) /*插在第一个节点之前*/
else /*p是q的前驱*/
t-&next = /*完成插入动作*/
/*first = first-&*/
} head是头节点,是空的,for里令q=head,那么那个for循环里是怎么执行的,刚开始就终止循环了不是吗
缺牙要及时修复,揭秘种植牙如何做到几十年不掉?
自己看限定
first = head-&while (first != NULL)forfirst是head的下一个,first不为NULL,head肯定不为NULL
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或C语言两个无序单链表,排序后合并成一个有序链表
算法思想:用冒泡法,对链表1和2进行排序,对排序后的两个链表,从小到大进行循环,装入链表3中。
#include&stdio.h&
#include&stdlib.h&
struct stud/*定义链表*/
struct stud *
void pai_xue(struct stud *head1,struct stud *head2,int count1,int count2)/*冒泡排序法*/
int i,j,temp=0;
struct stud *p;
for(i=0;i&count1-1;++i)
for(p=head1-&p-&next!=NULL;p=p-&next)/*对链表1进行排序*/
if(p-&data&p-&next-&data)
p-&data=p-&next-&
p-&next-&data=
for(i=0;i&count2-1;++i)
for(p=head2-&p-&next!=NULL;p=p-&next)/*对链表2进行排序*/
if(p-&data&p-&next-&data)
p-&data=p-&next-&
p-&next-&data=
printf(&\n链表1排完序后\n&);/*输出链表1和2*/
printf(&%d&,p-&data);
printf(&\n&);
printf(&\n链表2排完序后\n&);
printf(&%d&,p-&data);
printf(&\n&);
void main()
struct stud *head1,*head2,*p,*q,*head3;
int count1=1,count2=1;
head3=(struct stud *)malloc(sizeof(struct stud *));/*定义链表头结点,并分配空间*/
head3-&next=NULL;
head1=(struct stud *)malloc(sizeof(struct stud *));
head2=(struct stud *)malloc(sizeof(struct stud *));
p=(struct stud *)malloc(sizeof(struct stud *));
q=(struct stud *)malloc(sizeof(struct stud *));
head1-&next=NULL;
head2-&next=NULL;
printf(&输入一个数据以999结束\n&);
scanf(&%d&,&p-&data);
while(p-&data!=999)/*链表1输入数据*/
p-&next=head1-&
head1-&next=p;
printf(&输入一个数据以999结束\n&);
p=(struct stud *)malloc(sizeof(struct stud *));
scanf(&%d&,&p-&data);
printf(&现在开始给第二个链表输入数据\n&);
printf(&输入一个数据以999结束\n&);
scanf(&%d&,&q-&data);
while(q-&data!=999)/*链表2输入数据*/
q-&next=head2-&
head2-&next=q;
printf(&输入一个数据以999结束\n&);
q=(struct stud *)malloc(sizeof(struct stud *));
scanf(&%d&,&q-&data);
pai_xue(head1,head2,count1,count2);
head1=head1-&
head2=head2-&
while(head1!=NULL&&head2!=NULL)/*将排序好的链表1和2 的数据导入链表3*/
if(head1-&data&=head2-&data)
head1-&next=head3-&
head3-&next=head1;
head2-&next=head3-&
head3-&next=head2;
if(head1!=NULL)/*如果有链表1或2的数据不为空,将剩下的数据导入链表3中*/
while(p!=NULL)
p-&next=head3-&
head3-&next=p;
if(head2!=NULL)
while(q!=NULL)
q-&next=head3-&
head3-&next=q;
q=head3-&/*将链表倒置,原来是由大到小,倒置成由小到大*/
head3-&next=NULL;
while(q!=NULL)
q-&next=head3-&
head3-&next=q;
printf(&两个链表合并后由小到大为\n&);
printf(&%d&,p-&data);
C语言两个无序单链表,排序后合并成一个有序链表
标签(Tag):
------分隔线----------------------------
------分隔线----------------------------
Windows下的编程工具使用 VC 6.0,下面讲解如何在VC 6.0下运行上节的Hello, world程序...
Microsoft Visual C++ 是微软公司推出的、在 Windows 下的可视化集成编程系统,也是广...
简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: local t...
协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针,...
刚刚加班回来;哎,公司规定平时加班只有10块钱的餐补;星期六和星期天加班,只给串休...
什么是RegisterHotKey? RegisterHotKey函数被用来定义一个系统范围的热键;那什么是...}

我要回帖

更多关于 c语言链表详解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信