//链表的使用

#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. Android NDK

    1.Android之NDK开发 http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html

  2. FileReader和FileWriter

    FileReader和FileWriter 使用fileoutputstream类向文件写入数据与使用fileinputstream类从文件中将内容读取出来,存在不足,就是中文占两个字节, 搞不好就会 ...

  3. c语言 拼接字符串

    #include<stdio.h> #include<stdlib.h> void main() { ] = "ca"; ] = "lc" ...

  4. iOS开发之网络数据解析(二)--XML解析简介

    前言:本篇随笔介绍的是XML解析. 正文: 1.XML解析方式有2两种: DOM:一次性将整个XML数据加载进内存进行解析,比较适合解析小文件 SAX:从根元素开始,按顺序一个元素一个元素往下解析,比 ...

  5. android 之 spinner的简单使用

    先看spinner的效果图: 代码: MainActivity package com.mecury.spinnertest; import java.util.ArrayList; import a ...

  6. iOS开发者必备的10款工具

    当前iOS和Android两大移动操作系统“二足鼎立”,几乎覆盖了市面上大部分的智能手机.相比Android,iOS开发适配更简单,且随着各种实用工具和Swift语言的出现,iOS开发门槛地降低,开发 ...

  7. Effective Java 34 Emulate extensible enums with interfaces

    Advantage Disadvantage Enum types Clarity Safety Ease of maintenance. None extensibility Typesafe en ...

  8. Java并发大师Brain Goetz和Doug Lea 的中英文博客文章地址

    Java并发大师Brain Goetz和Doug Lea是Java并发方面最权威的人物,他的文章绝对是最具有参考价值的,值得仔仔细细的推敲和研究. Brain Goetz 中文地址:http://ww ...

  9. C标准头文件<assert.h>

    <assert.h>定义了两个用来调试程序的宏: assert和NDEBUG,assert用来判断表达式是否为真,如果为真继续执行,如果为假,向stderr输出一条错误消息,并调用< ...

  10. 工作中常用的Linux命令:目录

    工作两三年,每天都和Linux打交道,但每每使用Linux命令的时候却会像提笔忘字般不知如何使用,常常查手册或到网上找资料.此系列文章主要是为了方便自己在使用命令时随时可查阅.鄙人才疏学浅,文中若有任 ...