我对单向链表的学习
2015-09-11 16:13
155 查看
本文章主要是记述我对单向链表的理解:1.有头节点和无头结点链表的理解 2.有头结点链表的创建 ,显示,插入,删除,冒泡排序,逆置。
我对链表的理解就是将一个个结构体串联起来。一个个结构体在一个链表中就是一个节点,节点之间是由结构体指针联系起来的,也就是他们结构体中会包含一个同类型的*next指针,用来指向下一个节点的地址,这个就是节点的指针域,里面其他类型的数据就是节点的数据域。 头结点就是数据域为空(0),指针域是指向一个有效数据的一个结构体,它是一个节点,由malloc跟它分配了内存。
下面我用代码来分析:
首先创建一个结构体
下面就是各个功能函数
1.创建一个带头结点的链表:
2.显示链表的数据
3.链表插入结点(这个函数的功能是插在某个结点的后面)
3.链表删除结点:
这里为什么要找到删除结点的前一个位子呢?因为我们删了这个结点,但是还需要把这个结点的前后连接起来,组成一个链表,不然这里就断了,而且这个链表是单向的。
结点的删除很简单,只不过需要注意的是我们必须得把要删除的结点free掉,不然会造成内存泄露
4.链表的冒泡排序(按从小到大)
思路:就是将所有数据进行比较,小的放前面,第一次是所有数据比,最小的放第1个,然后是除了第一个数据的后面的再比较,最小的放第2个,以此类推。n个数据比较,
最多是比较n(n-1)/2,最少比较0次 ps:10个数据比较,最多就是9+8+7+.....+1,通项公式是前面那个式子。
5.链表的逆置(逆置后我仍然把它做成一个带头结点的链表,所以给创建了一个新的头结点new_h,把以前的那个free掉了)
q=p->next;
p->next=r;
r=p;
p=q;
第一次循环结束;
接下来继续循环
q=p->next;
p->next=r;
r=p;
p=q;
到最后逆置完所有数据
别忘记了我们还要插入头结点和将以前的那个头结点设置为null,这里有一点我改过的就是我以前将head结点free掉,现在是将其设置为null,如果是前者他们这个链表就没有null结束了,但是运行结果还是正确的,这里是我不懂的,反正2种方法最后运行还是可以的。
下面是我的main函数
下面是运行结果:
程序比较简单,应该会有bug,只是为了简单的学习一点链表。
我对链表的理解就是将一个个结构体串联起来。一个个结构体在一个链表中就是一个节点,节点之间是由结构体指针联系起来的,也就是他们结构体中会包含一个同类型的*next指针,用来指向下一个节点的地址,这个就是节点的指针域,里面其他类型的数据就是节点的数据域。 头结点就是数据域为空(0),指针域是指向一个有效数据的一个结构体,它是一个节点,由malloc跟它分配了内存。
下面我用代码来分析:
首先创建一个结构体
typedef struct list { int data;//数据域 struct list *next;//指针域 }node;
下面就是各个功能函数
1.创建一个带头结点的链表:
node *creat_link_list(int n) { node *head,*p,*pre; int i; head=(node*)malloc(sizeof(node));//创建一个头结点 head->next=NULL; pre=head;//用一个指针来指向这个头结点,这个指针是各个结点连接起来的关键 for(i=0;i<n;i++) { p=(node*)malloc(sizeof(node));//创建我们需要的数据结点 printf("input the %d data\n",i+1); scanf("%d",&p->data); pre->next=p;//将pre指向的结点和数据结点连接起来 pre=p;//再把第一个数据结点的位置给pre指针 }//如此循环,直到创建完你需要的结点 p->next=NULL; //然后将最后一个数据结点指向null,结束此单向链表 return head;//返回头结点的地址 }
2.显示链表的数据
void printlist(node *head) { node *p; p=head->next;//因为我们是有头结点的链表,所以head头结点的数据域为0,我们不需要,所以得把它的next地址给它 int i=1; while(p) { printf("the (%d)data= %d\n",i,p->data); i++; p=p->next; } }按照上面的程序,一直打印出各个结点的信息(除了头结点的),直到我们的链表结束,null。
3.链表插入结点(这个函数的功能是插在某个结点的后面)
void insertlist(node *head,int i,int is_data,int n) { node *p,*q; int j=0; p=head; while(j<i) { p=p->next; //遍历这个链表,找到你需要插的那个结点,第一个数据结点的下标我给的1,所以才是j=0,j<i这样设置遍历条件,大家慢慢体会,也可以自己画图,如果是想在头结点后面插一个数据,则i就输入0。 j++; } q=(node *)malloc(sizeof(node));//创建我们要插入的结点 q->data=is_data; q->next=p->next;//找到位置后将这个结点的next给我们创建的结点,然后再将这个位置结点的next指向我们创建的结点 p->next=q; }
3.链表删除结点:
void delietelist(node *head,int i) { node *p,*q; int j=0; p=head; while(j<i-1)//我们还是进行遍历,找到我们需要删除的结点的前一个结点位置,当然这里我们不能删除头结点,跟插入一样第一个数据结点我给的下标还是1,所以你想删除第一个数据结点的时候就只需要输入i=1 { p=p->next; j++; } q=p->next; p->next=q->next; free(q); }
这里为什么要找到删除结点的前一个位子呢?因为我们删了这个结点,但是还需要把这个结点的前后连接起来,组成一个链表,不然这里就断了,而且这个链表是单向的。
结点的删除很简单,只不过需要注意的是我们必须得把要删除的结点free掉,不然会造成内存泄露
4.链表的冒泡排序(按从小到大)
node * sort(node *head) { node *p,*q; int temp; p=head->next; for(;p->next!=NULL;p=p->next) { for(q=p->next;q!=NULL;q=q->next) { if(p->data>q->data) { temp=q->data; q->data=p->data; p->data=temp; } } } return head; }这个没什么说的,思路就是冒泡的思想,实现的时候只需要将数据换乘链表的形式即可。
思路:就是将所有数据进行比较,小的放前面,第一次是所有数据比,最小的放第1个,然后是除了第一个数据的后面的再比较,最小的放第2个,以此类推。n个数据比较,
最多是比较n(n-1)/2,最少比较0次 ps:10个数据比较,最多就是9+8+7+.....+1,通项公式是前面那个式子。
5.链表的逆置(逆置后我仍然把它做成一个带头结点的链表,所以给创建了一个新的头结点new_h,把以前的那个free掉了)
node * reverse_list(node *head) { node *p,*q,*r,*new_h; r=NULL; q=NULL; new_h=(node*)malloc(sizeof(node)); p=head->next; while(p) { q=p->next; p->next=r; r=p; p=q; } head=NULL; new_h->next=r; return new_h; }
q=p->next;
p->next=r;
r=p;
p=q;
第一次循环结束;
接下来继续循环
q=p->next;
p->next=r;
r=p;
p=q;
到最后逆置完所有数据
别忘记了我们还要插入头结点和将以前的那个头结点设置为null,这里有一点我改过的就是我以前将head结点free掉,现在是将其设置为null,如果是前者他们这个链表就没有null结束了,但是运行结果还是正确的,这里是我不懂的,反正2种方法最后运行还是可以的。
下面是我的main函数
int main(int argc,char *argv[]) { node * head; int i,data,n; printf("please input the number of the data list: \n"); scanf("%d",&n); head=creat_link_list(n); printf("list elements:\n"); printlist(head); printf("input the position of insert elements:\n"); scanf("%d",&i); if(i>n) { printf("lager than the ranger\n"); exit(0); } else printf("input data :\n"); scanf("%d",&data); insertlist(head,i,data,n); printf("list elements\n"); printlist(head); printf("input the position of delete elements:\n"); scanf("%d",&i); delietelist(head,i); printlist(head); printf("sort the list\n"); head=sort(head); printlist(head); printf("list the reverse list:\n"); head=reverse_list(head); printlist(head); return 0; }
下面是运行结果:
程序比较简单,应该会有bug,只是为了简单的学习一点链表。
相关文章推荐
- 【iOS】UIButton 图标在上文字在下
- 中年人做到四点百病消
- 关于 datasnap Stream的英文博客能容
- 微信生成公众号带参数二维码用户头像 加上文字生成图片(三)
- iOS Layer动画收集
- 把IP地址转换成INT型存储(考察的位运算)
- java导出Excel文档
- sql判断库、表、列、存储过程、视图、函数存在性与创建
- 转 hibernate.hbm2ddl.auto配置详解
- 字符串移位之翻手算法
- 两个有序数组中找第N个数
- poi生成word文件
- 微信生成公众号带参数二维码加上用户头像(二)
- 10分钟学会使用qmake
- 解决 Oracle 描述乱码问题
- 解决xnamath.h找不到的问题
- android项目迁移到新android studio所遇到的Gradle问题汇总
- UE4 HLSL Cross Compiler
- 「深度优先遍历」 输出电话号码对应的英语单词
- Dom4j初步使用