C语言讲义——链表完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
int _id;
char s[50];
struct Node* pre;// 指向前一个节点的地址
struct Node* next;// 指向下一个节点的地址
};
void node_free(struct Node** q) {
if( *q != NULL) {
printf("free %d\n",(*q)->_id);
free(*q);
*q = NULL;
}
}
void node_print(struct Node* q) {
if (NULL == q) {
puts("节点打印:空节点,无可打印");
return;
}
printf("preview=%10d ", q->pre);
printf("【address=%10d】 ", q);
printf("【id=%2d】", q->_id);
printf("next=%10d\n", q->next);
}
void chain_print(struct Node* qFirst) {
if (qFirst == NULL) {
puts("没有元素可以打印");
return;
}
puts("----------↓↓↓打印链表------------");
// 遍历链表
struct Node* q;
for(q = qFirst; q != NULL; q=q->next ) {
node_print(q);
}
puts("----------↑↑↑打印链表------------");
}
/*
* 为链表追加节点(加在最后)
* 参数:头节点,需要追加的节点
* 返回值:无
*/
void chain_add(struct Node* qFirst, struct Node* qAdd) {
// 定位到链表头
struct Node* q = qFirst;
// 只要后面(next)有节点,往后找;直到没有next的节点(最后一个)
for(q; q->next!= NULL; q=q->next ) {
//node_print(q);
}
// 此时定位在最后一个节点,下图1
// 将新节点加在最后节点的后面(next)
q->next = qAdd;// 下图2
qAdd->pre = q;//下图3
}
/*
* 删除节点
* 参数:1.头结点 2.待删除的结点
* 因为被删除的结点需要置空,所以需要使用二级指针
* 返回值:-1 删除失败/0 删除成功
*/
int chain_remove(struct Node** qFirst, struct Node** qRemove) {
struct Node* qPre = NULL;
struct Node* qNext = NULL;
struct Node* q = *qFirst;
// 1.输入Check
if(NULL == *qRemove) {
puts("删无可删!");
return -1;
} else {
printf("删除节点:id=%d\n", (*qRemove)->_id);
}
// 2.删除头结点,特殊对待
if(*qFirst == *qRemove ) {
if((*qFirst)->next == NULL) {
// 就一个头结点的场合
node_free(qFirst);
} else { // 见下图4
qNext = q->next;
node_free(qFirst);
*qFirst = qNext;
}
printf("---chain_remove(头结点):%d\n", *qFirst);
return 0;
}
// 3.遍历链表
for(q; q != NULL; q=q->next ) {
if (q == *qRemove) {
qPre = q->pre;
qNext = q->next;
if (qNext!=NULL) {// 见下图5
qNext->pre = qPre;
qPre->next= qNext;
} else {
// 尾节点的场合,见下图6
qPre->next= NULL;
}
node_free(qRemove);
return 0;
}
}
}
void chain_clear(struct Node** qFirst) {
puts("\n----------Clear------------");
if (qFirst == NULL) {
puts("已经是空");
return;
}
// 遍历链表
// 不断删除第一个元素
while(*qFirst != NULL) {
chain_remove(qFirst,qFirst);
printf("---chain_clear():头结点 %d\n", *qFirst);
}
}
struct Node* chain_get(struct Node* qFirst, int index) {
printf("---获取index = %d的节点:", index);
int i = 0;
// 遍历链表
struct Node* q = qFirst;
for(q; q!= NULL; q=q->next,i++ ) {
if (index == i) {
return q;
}
}
return NULL;
}
/*
* 获取链表长度(即节点的个数)
* 参数:头节点
* 返回值:链表长度
*/
int chain_count(struct Node* qFirst) {
if (qFirst == NULL) {
// 头节点都没有,长度为0
return 0;
}
int i = 0;
// 遍历链表
struct Node* q = qFirst;
for(q; q != NULL; q=q->next) {
// 顺藤摸瓜,直到最后一个节点
i++;// 找到一个就+1
}
return i;
}
struct Node* node_new(int id) {
struct Node* q = (struct Node*)malloc(sizeof(struct Node));
memset(q, 0, sizeof(struct Node));
q->_id = id;
return q;
}
int g_id = 1;
struct Node* qHead = NULL;
void test0Node() {
puts("###0节点的链表:");
printf("count = %d\n",chain_count(NULL));
chain_print(NULL);
}
void testAddNode() {
puts("\n###添加一个节点:");
struct Node* _q = node_new(g_id++);
chain_add(qHead, _q);
printf("count = %d\n",chain_count(qHead));
chain_print(qHead);
}
void test3Node() {
testAddNode();
testAddNode();
testAddNode();
chain_print(qHead);
}
void testGetNode() {
puts("输入需要get的节点的id");
int nId;
scanf("%d", &nId);
getchar();
struct Node* pGet;
pGet = chain_get(qHead, nId);
node_print(pGet);
}
void testRemoveNode() {
puts("输入需要删除的节点的id");
int nId;
scanf("%d", &nId);
getchar();
struct Node* pGet;
pGet = chain_get(qHead, nId);
node_print(pGet);
chain_remove(&qHead, &pGet);
}
void menu() {
puts("***********************");
puts("0.空链表打印");
puts("1.添加1个节点");
puts("3.添加3个节点");
puts("4.获取节点");
puts("5.打印链表");
puts("7.删除节点");
puts("8.清空节点");
puts("9.清屏");
puts("其它数字.退出");
if (NULL== qHead) {
qHead = node_new(g_id++);
puts("生成头结点");
}
puts("***********************");
}
void testMain() {
while(1) {
menu();
int nSelect = 0;
scanf("%d", &nSelect);
getchar();
switch(nSelect) {
case 0:
test0Node();
break;
case 1:
testAddNode();
break;
case 3:
test3Node();
break;
case 4:
testGetNode();
break;
case 5:
chain_print(qHead);
break;
case 7:
testRemoveNode();
break;
case 8:
chain_clear(&qHead);
break;
case 9:
system("cls");
break;
default:
return;
}
}
}
int main(int argc, char** argv) {
testMain();
return 0;
}
C语言讲义——链表完整代码的更多相关文章
- C语言讲义——链表的实现
节点(结构体描述) struct Node { int _id; char s[50]; struct Node* pre;// 指向前一个节点的地址 struct Node* next;// 指向下 ...
- AVL树,C语言实现,完整代码,先贴上,讲解稍后
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #de ...
- C语言实现推箱子游戏完整代码
C语言实现推箱子游戏完整代码 前言 自己做的,可能有些代码不够工整,或者有些小问题,但游戏的基本操作是可以实现的 代码效果 代码一共分为8个部分,4个控制上下左右移动,2个判断输赢,1个统计归为的个数 ...
- C语言创建链表
一.链表中结点的存储 链表的结点左边一部分是存放的数据,右边一部分是后继指针指向下一个结点的地址.C语言中通常定义一个结构体类型来存储一个结点,如下: struct node { int data; ...
- C语言实现链表(链式存储结构)
链表(链式存储结构)及创建 链表,别名链式存储结构或单链表,用于存储逻辑关系为 "一对一" 的数据.与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其 ...
- C语言之链表
这两天在复习C语言的知识,为了给下个阶段学习OC做准备,以下的代码的编译运行环境是Xcode5.0版本,写篇博文把昨天复习的C语言有关链表的知识给大家分享一下,以下是小菜自己总结的内容,代码也是按照自 ...
- C语言描述链表的实现及操作
一.链表的创建操作 // 操作系统 win 8.1 // 编译环境 Visual Stuido 2017 #include<stdio.h> #include<malloc.h> ...
- MSScriptControl详解(可实现在C#等语言中调用JAVASCRIPT代码)
ScriptControl接口 属性名称 类型 备注 AllowUI BOOL 检测是否允许运行用户的接口元素.如果为False,则诸如消息框之类的界面元素不可见. CodeObject Object ...
- YTU 2430: C语言习题 链表建立,插入,删除,输出
2430: C语言习题 链表建立,插入,删除,输出 时间限制: 1 Sec 内存限制: 128 MB 提交: 576 解决: 280 题目描述 编写一个函数creatlink,用来建立一个动态链表 ...
随机推荐
- jdk1.8特性2
public class User { private Long id; private String userName; private String roleName; private Strin ...
- CopyOnWriteArrayList线程安全分析
CopyOnWriteArrayList是开发过程中常用的一种并发容器,多用于读多写少的并发场景.但是CopyOnWriteArrayList真的能做到完全的线程安全吗? 答案是并不能. 一.Copy ...
- 记EF的一个基本访问类
代码: 1 using EFModel; 2 using System; 3 using System.Collections.Generic; 4 using System.Data.Entity; ...
- idea 远程debug springboot
idea 远程debug springboot 1.新建一个springboot工程. 新建一个controller接口 @RestController @RequestMapping public ...
- thinkphp之无限分类
namespace Home\Controller; use Home\Controller; class CategoryController extends Controller { //无限分类 ...
- Centos 7挂载本地ISO光盘
在Linux系统上挂载系统镜像作为yum本地仓库或者安装某个常用RPM包. mount语法: mount -t 类型 -o 挂接方式 源路径 目标路径 -t 选项: iso9660:光盘或光盘镜像 m ...
- 水题挑战6: CF1444A DIvision
A. Division time limit per test1 second memory limit per test512 megabytes inputstandard input outpu ...
- KMP算法和bfprt算法总结
目录 1 KMP算法 1.1 KMP算法分析 1.2 KMP算法应用 题目1:旋转词 题目2:子树问题 2 bfprt算法 2.1 bfprt算法分析 2.2 bfprt算法应用 1 KMP算法 大厂 ...
- linux kernel 的 procfs sysfs 对查问题的帮助
遇到进程卡死,没有gdb 符号表:只能strace 跟踪处理分析 排查过程: 1.ps -aux 查看卡死进程pid 2.strace -T -tt -e trace=all -p 查看卡死进程系统调 ...
- t分布与t检验的一点理解
最近又遇到了t分布及t检验方面的内容,发现有些地方自己当初没有很明白,就又查了些资料,加深了一下自己的理解,这里也将自己的一些理解记录下来. 1. 理论基础--大数定理与中心极限定理 在 ...