//链表的使用

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h> //定义链表结构体
struct LinkCode{
int num;
char sname[];
struct LinkCode * linknext;
}; //静态链表
void Linkone(){
struct LinkCode n1, n2, n3, n4, n5;
struct LinkCode * head = NULL;
//初始化变量
n1.num = ;
sprintf(n1.sname, "小明");
n1.linknext = &n2; n2.num = ;
sprintf(n2.sname, "小红");
n2.linknext = &n3; n3.num = ;
sprintf(n3.sname, "小芳");
n3.linknext = &n4; n4.num = ;
sprintf(n4.sname, "小刚");
n4.linknext = &n5; n5.num = ;
sprintf(n5.sname, "小志");
n5.linknext = NULL; printf("\n==========静态链表============\n"); //循环遍历----查询
printf("\n==========查询============\n");
for (head = &n1; head!= NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //增加
printf("\n==========增加============\n");
struct LinkCode n6;
n6.num = ;
sprintf(n6.sname, "小雨"); struct LinkCode n7;
n7.num = ;
sprintf(n7.sname, "小丽"); //情景1,插入末尾
printf("\n==========增加到末尾============\n");
n5.linknext = &n6;
n6.linknext = NULL;
//循环遍历----查询
for (head = &n1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //情景2,插入到中间2后面
printf("\n==========增加到中间============\n");
struct LinkCode *px=NULL;
for (head = &n1; head != NULL; head = head->linknext)
{
//注意for循环的执行顺序
if (head->num==)
{
px = head->linknext;
head->linknext = &n7;
n7.linknext = px;
}
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //修改
printf("\n==========修改============\n");
//把小红的num修改成99
for (head = &n1; head != NULL; head = head->linknext)
{
//strcmp()函数 串比较 str1>str2,返回值 > 0;两串相等,返回0
if (!strcmp(head->sname,"小红"))
{
head->num = ;
}
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //删除
printf("\n==========删除============\n");
//删除num是7的节点
for (head = &n1; head != NULL; head = head->linknext)
{
if (head->num==)
{
//找到该节点的地址,再次重新开始循环遍历
px = head;
}
} for (head = &n1; head != NULL; head = head->linknext)
{
if (head->linknext==px)
{
//找到要删除节点的上一个节点
head->linknext = px->linknext;
}
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} printf("\n");
} //动态链表
void LinkTwo(){
struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
head = p1 = p2 = p3 = p4 = p5 = NULL;
//先分配内存
p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode)); p1->num = ;
sprintf(p1->sname, "小明1");
p1->linknext = p2; p2->num = ;
sprintf(p2->sname, "小红1");
p2->linknext = p3; p3->num = ;
sprintf(p3->sname, "小芳1");
p3->linknext = p4; p4->num = ;
sprintf(p4->sname, "小刚1");
p4->linknext = p5; p5->num = ;
sprintf(p5->sname, "小志1");
p5->linknext = NULL; printf("\n==========查询============\n");
//循环打印
for (head = p1; head != NULL; head=head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //增加
printf("\n==========增加============\n"); struct LinkCode *p6 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
struct LinkCode *p7 = (struct LinkCode *)malloc(sizeof(struct LinkCode)); p6->num = ;
sprintf(p6->sname, "小雨1");
p6->linknext = NULL; p7->num = ;
sprintf(p7->sname, "小丽1");
p7->linknext = NULL; //情景1,在末尾追加
p5->linknext = p6;
printf("\n==========增加(在末尾追加)============\n");
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} printf("\n==========增加(在中间追加)============\n");
struct LinkCode *py = NULL;
//情景2,在中间追加(追加在小红后面)
for (head = p1; head != NULL; head = head->linknext)
{
if (!strcmp(head->sname, "小红1"))
{
py = head->linknext;
head->linknext = p7;
p7->linknext = py;
}
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //修改
printf("\n==========修改============\n");
p1->num = ;
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //删除
printf("\n==========删除============\n");
//删除节点num=4的节点
for (head = p1; head != NULL; head = head->linknext)
{
if (head->num==)
{
//找到要删除的节点
py = head;
}
}
for (head = p1; head != NULL; head = head->linknext)
{
if (head->linknext==py)
{
head->linknext = py->linknext;
free(py);
//注意:动态链表的删除和静态链表的删除不同,静态链表创建是在栈中,而动态链表是用malloc()函数创建
//所以动态链表在堆中,想要删除必须程序员手动用free()函数删除
}
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} printf("\n");
} //链表销毁
void ClearLink(){
printf("\n==========创建链表============\n");
struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
head = p1 = p2 = p3 = p4 = p5 = NULL;
//先分配内存
p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode)); p1->num = ;
sprintf(p1->sname, "小明1");
p1->linknext = p2; p2->num = ;
sprintf(p2->sname, "小红1");
p2->linknext = p3; p3->num = ;
sprintf(p3->sname, "小芳1");
p3->linknext = p4; p4->num = ;
sprintf(p4->sname, "小刚1");
p4->linknext = p5; p5->num = ;
sprintf(p5->sname, "小志1");
p5->linknext = NULL; printf("\n==========查询============\n");
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //销毁链表(只要给我一个头结点的地址,我能够删除整个链表)
printf("\n==========销毁链表============\n");
//思路:一个个删除,保留第一个,删除第二个,把第三个重新连接成第二个
struct LinkCode *pt = NULL;
//循环打印
while (p1->linknext!=NULL){
//获取第二个的地址
pt = p1->linknext;
//把第三个的地址放到第一个后面
p1->linknext = p1->linknext->linknext;
//删除第二个
free(pt);
}
//当p1->linknext!=NULL时,表示整个链表只剩下第一个了
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
}
//此时再删除第一个
free(head);
printf("\n头结点的指针地址%x", head);
} //链表逆转
void sort(){
printf("\n==========创建链表============\n");
struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
head = p1 = p2 = p3 = p4 = p5 = NULL;
//先分配内存
p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode)); p1->num = ;
sprintf(p1->sname, "小明1");
p1->linknext = p2; p2->num = ;
sprintf(p2->sname, "小红1");
p2->linknext = p3; p3->num = ;
sprintf(p3->sname, "小芳1");
p3->linknext = p4; p4->num = ;
sprintf(p4->sname, "小刚1");
p4->linknext = p5; p5->num = ;
sprintf(p5->sname, "小志1");
p5->linknext = NULL; printf("\n==========查询============\n");
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //链表逆转(只给头结点的地址)
printf("\n==========链表逆转============\n");
//思路;存储第一个的地址,让第一个的下一个是NULL,第二个的下一个是原来的第一个,第三个下一个是原来的第二个
head = p1;
struct LinkCode *px = head;//头结点
struct LinkCode *py = head->linknext;//第二个节点
struct LinkCode *pz = NULL;
while (py!=NULL){
pz = py->linknext;//第三个节点
//开始逆转
py->linknext = px;//将第二个节点的下个节点赋值为第一个节点的地址
//开始将所有指针向前移动1位
px = py;//将第一个节点向前移动1位(移动到第二个节点的位置)
py = pz;//将第二个节点向前移动1位(移动到第三个节点的位置)
//此时再次进入循环 pz = py->linknext; 这会将第三个节点的值变成第四个节点
//当py->linknext==NULL(即pz =NULL)的时候;表明此时py已经是链表最后一个节点了,
//那么py->linknext的值就必须是链表倒数第二个的地址,所以还需要再循环1次,给py->linknext赋值,
//再次经过py = pz;此时py==NULL;
}
//这个时候原来的第一个节点的linknext属性的值还是第二个节点的地址,,这是错误的,应该置为空
head->linknext = NULL;
//此时px就是原来链表最后一个节点的地址,因为head必须是头结点并且链表已经逆转了,
//所以head的值不能是原来的第一个节点,而应该是原来链表最后一个节点的地址
head = px;
//循环打印
for (head; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} } //链表排序(方法1)
//方法1:交换2个元素的位置
//缺点:理解复杂,操作麻烦
//链表的冒泡排序与数组有巨大区别
//数组每个元素都可以单独确定,a[1]就是第二个元素
//但是链表他的每个元素都是由他的上一个元素确定,不存在有多少个元素的概念,只是上一次可以找到下一个
void Sort2(){
printf("\n==========创建链表============\n");
struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
head = p1 = p2 = p3 = p4 = p5 = NULL;
//先分配内存
p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode)); p1->num = ;
sprintf(p1->sname, "小明1");
p1->linknext = p2; p2->num = ;
sprintf(p2->sname, "小红1");
p2->linknext = p3; p3->num = ;
sprintf(p3->sname, "小芳1");
p3->linknext = p4; p4->num = ;
sprintf(p4->sname, "小刚1");
p4->linknext = p5; p5->num = ;
sprintf(p5->sname, "小志1");
p5->linknext = NULL; printf("\n==========查询============\n");
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //链表排序(只给头结点的地址)---由小到大
printf("\n==========链表排序============\n");
//思路;定义3个变量,因为链表无法通过当前元素获取上一个元素,所以只能用一个变量将上一个变量的地址记录下来 //px--代表第一个元素,py代表第二个元素,pz代表第三个元素
//参与比较的是py与pz
struct LinkCode * px, *py, *pz;
//初始化指针,防止后面出错
px = py = pz=NULL;
//在比较链表前2个元素的时候,第一个元素没有上一个元素,所以px=py=head
px =py= head=p1; //冒泡排序,每循环一次,会将一个最大值移动到末尾,每移动一次,需要移动的元素就会少一个
//一共5个元素,移动4次后,最大的元素都已经放到链表末尾
int index = ;
while (index){//外层循环
//获取第三个元素的值
pz = py->linknext;
if (py->num>pz->num)
{
//如果第一个节点的num比第二个大,则要求交换位置
//1.把第一个节点的下个节点属性赋值为第三个节点的地址
//此时px是第一个元素
px->linknext = pz;
//2.把第二个节点的下个节点属性赋值为第四个节点的地址
py->linknext = pz->linknext;
//3.把第三个节点的下个节点属性赋值为第二个节点的地址
pz->linknext = py;
//第一组交换完成
//4.将所有节点向前移动一位,这里px已经不是第一个元素了,他往前移动1位
//因为要确定头结点的值,所以前2个元素的比较,必须单独提取出来
head = px = pz;
}
do{
pz = py->linknext;
if (py->num>pz->num)
{
//如果第一个节点比第二个大,则要求交换位置
//1.把第一个节点的下个节点属性赋值为第三个节点的地址
px->linknext = pz;
//2.把第二个节点的下个节点属性赋值为第四个节点的地址
py->linknext = pz->linknext;
//3.把第三个节点的下个节点属性赋值为第二个节点的地址
pz->linknext = py;
//第一组交换完成
//4.将所有节点向前移动一位
px = pz;
}
else{
//如果大小顺序正确,3个元素都需要再向前移动1位;
//把第二个元素赋值给原来第一个元素
px = py;
//把第三个元素赋值给原来第二个元素
py = pz;
}
} while (py->linknext != NULL);//判断第三个元素是否是空
//再次初始化
//因为此时px,py,pz都已经移动到链表末尾
px = py = head;
pz = py->linknext;
index--;
} //循环打印
for (head; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} } //链表排序(方法2)
//方法1:交换2个元素的内容,不改变链表节点的位置,只是内容的交换
//优点:操作简单,通俗易懂
void Sort3(){
printf("\n==========创建链表============\n");
struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
head = p1 = p2 = p3 = p4 = p5 = NULL;
//先分配内存
p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode)); p1->num = ;
sprintf(p1->sname, "小明1");
p1->linknext = p2; p2->num = ;
sprintf(p2->sname, "小红1");
p2->linknext = p3; p3->num = ;
sprintf(p3->sname, "小芳1");
p3->linknext = p4; p4->num = ;
sprintf(p4->sname, "小刚1");
p4->linknext = p5; p5->num = ;
sprintf(p5->sname, "小志1");
p5->linknext = NULL; printf("\n==========查询============\n");
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} //链表排序(只给头结点的地址)---由小到大
printf("\n==========链表排序============\n"); struct LinkCode *px = NULL;
struct LinkCode *py = NULL;
struct LinkCode sz; for (px = head = p1; px != NULL; px = px->linknext)
{
for (py = head = p1; py != NULL; py = py->linknext)
{
//双循环
//外循环的一个元素跟其他5个元素相比较,只要px<py就会发生交换
//导致当2是最小元素的时候,他必须先跟前面比他大的所有元素,把自己变成最大,并非单单与最大元素进行交换
//也就是小元素会不断的被推到最前面
if (px->num<py->num)
{
sz.num = px->num;
px->num = py->num;
py->num = sz.num; sprintf(sz.sname, px->sname);
sprintf(px->sname, py->sname);
sprintf(py->sname, sz.sname);
}
}
}
//循环打印
for (head = p1; head != NULL; head = head->linknext)
{
printf("\nnum=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
} } void main(){
//Linkone();
//LinkTwo();
//ClearLink();
//sort();
//Sort2();
Sort3(); system("pause");
}

C语言 链表的使用(链表的增删查改,链表逆转,链表排序)的更多相关文章

  1. DataGridView绑定泛型List时,利用BindingList来实现增删查改

    DataGridView绑定泛型List时,利用BindingList来实现增删查改  一.   DataGridView绑定泛型List的种种 1.DataGridView数据绑定对比(DataTa ...

  2. 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  3. 8天学通MongoDB——第二天 细说增删查改

    原文地址:http://www.cnblogs.com/huangxincheng/archive/2012/02/19/2357846.html 看过上一篇,相信大家都会知道如何开启mongodb了 ...

  4. 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性

    基于.net的分布式系统限流组件   在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...

  5. 在MVC中使用泛型仓储模式和依赖注入实现增删查改

    标签: 原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository ...

  6. golang使用json格式实现增删查改

    需求和思路 在一般的小项目或者一个小软件,例如客户端之类的小程序中,可能会需要数据的持久化.但是使用一般的数据库(Mysql)之类的不合适.使用sqlite3这种嵌入式的是个较好的方法,但是Go语言中 ...

  7. 学习记录——使用PHP实现数据增删查改等基本功能(前后端分离)

    萌新初次学习服务器端语言,分享学习经验 实现功能:1.显示数据表    2.对数据进行分页    3.对数据进行增删查改 由于本萌新采用前后端完全分离方案,所以数据传输用的ajax,为了提高代码的复用 ...

  8. 3.EF 6.0 Code-First实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-entity-framework-5-0-code- ...

  9. 4.在MVC中使用仓储模式进行增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-using-the-repository-pattern-in-mvc/ 系列目录: ...

  10. 5.在MVC中使用泛型仓储模式和工作单元来进行增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

随机推荐

  1. dict和set

    #dict和set #dict #Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map #使用键-值(key-value)存储,具有极快的查找速度. #字 ...

  2. iOS 利用长按手势移动 Table View Cells

    本文译自:Cookbook: Moving Table View Cells with a Long Press Gesture 目录: 你需要什么? 如何做? 如何将其利用至UICollection ...

  3. win8下出现安装sql2012 正在启动操作系统功能"NetFx3"

    今天上午装win8系统,发现在装sql server 2012的时候,一直停在"正在启动操作系统功能"NetFx3""不动了,在网上找了下相关的资料,发现原来N ...

  4. 使用Android studio创建的AIDL编译时找不到自定义类的解决办法

    使用AS创建ADIL文件时AS会在main文件夹下给我们生成一个aidl文件夹和一个相同包名的包,通常我们会把所有和ADIL相关的类或文件放在这个包下,但是如果存在自定义的类时,程序编译时无法通过,提 ...

  5. OOD沉思录 --- 类和对象的关系 --- 包含关系3

    4.7 类包含的对象数目不应当超过开发者短期记忆数量,这个数目通常应该是6左右 4.8 让系统在窄而深的包含体系中垂直分布 假设有如下两份菜单: 正餐 --->甜瓜 --->牛排 ---& ...

  6. MongoDB学习笔记——MongoDB 连接配置

    MongoDB连接标准格式: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[dat ...

  7. 《SQL Server企业级平台管理实践》读书笔记——当我们的备份都已经损坏的时候该怎么办

    作为数据库管理员最最痛苦的莫过于,当数据库宕机的时候需要找备份,但在这个时候突然发现备份文件也是坏的,这就意味着数据会丢失,为此可能会丢掉职位,饭碗不保,所以为此,我们一定要保证好备份的完整性,一般发 ...

  8. Mysql 高负载排查思路

    Mysql 高负载排查思路 发现问题 top命令 查看服务器负载,发现 mysql竟然百分之两百的cpu,引起Mysql 负载这么高的原因,估计是索引问题和某些变态SQL语句. 排查思路 1. 确定高 ...

  9. ehcache整合spring本地接口方式

    一.简介 ehcache整合spring,可以通过使用echache的本地接口,从而达到定制的目的.在方法中根据业务逻辑进行判断,从缓存中获取数据或将数据保存到缓存.这样让程序变得更加灵活. 本例子使 ...

  10. Eclipse修改Tomcat发布路径以及的配置多个Tomcat方法

    最近放弃了使用Myeclipse,转而使用eclipse作为开发工具,确实Myeclipse集成了太多东西,使得开发人员的配置越来越少,这 不是个好事,使用eclipse后,有些地方就得自己去配置,比 ...