C语言深入探索之单链表与typedef的用法

目录
  • 前言
  • 详解typedef关键字
    • 含义
    • 具体使用
  • 详解单链表参数形式
    • 指针知识补充
    • 单链表形参详解
  • 单链表实战案例
    • 完整代码实现
      • 详解头插建表
      • 运行效果

前言

昨天博主去本站问答贴子逛了逛,然后发现了好多关于数据结构线性表,具体来说是单链表的问题。有的是没有一点思路,无从下手;有的是看不懂代码,不理解关键字以及被形参的形式气的不行,我总结了一下常见问题来给大家带来干货,到后面还有简单案例来巩固知识,弄透一题胜无脑刷百题,接下来是正文内容。

详解typedef关键字

含义

C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等。一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。

具体使用

单链表结点示例:

typedef struct node
{
	int data;//数据域
	struct node * next;//指针域
}Lnode, * SLinkList;

这里我们创建了 node 结构体,结构体里面包含了 整型数据data,指针next 指向下一个结点的地址。可以看到下面大括号外有 Lnode和*SLinkList。他的意思就是我们给node 起了一个别名叫Lnode,Lnode具有和node相同的结构,struct node n1与Lnode n1 效果完全相同;同时C语言还允许在结构中包含指向它自己的指针,即 SLinkList L 等价于 struct node* L 或者 Lnode *L;

详解单链表参数形式

指针知识补充

示例:

//1、
int* getValue1(int *&L)
{
	int a = 10;
	L = &a;
	return L;
}
//2、
int* getValue2(int *L)
{
	int a = 10;
	L = &a;
	return L;
}
int main()
{
	int* ptr = (int*)malloc(sizeof(int) * 4);
	getValue1(ptr);
    getValue2(ptr);
	cout << *ptr << endl;
}

我在主函数中为指针ptr动态分配了内存空间,大小为4*4字节,不理解的可以参考我的这篇博文详解数据结构线性表里面的动态分布内存函数malloc;然后将地址传递到上面两个函数里面去,输出getValue1 的*ptr 结果是10,但是getValue2 中*ptr 的结果却是乱码。那么原因很明显,就是参数 int *&L和 int *L的区别了。这个函数的返回值是一个地址,然而在栈区开辟的数据,在函数调用结束后就会被编译器自动释放掉,从而返回的地址不会是&a,因此仅仅使用地址传递是不行的。那么加上&为什么就可以了呢,这是因为我们的目的是改变传入指针所指向的地址,第一种只能改变该地址对应的数值,第二种可以从本质上更改地址,所以能得到 &a 从而*ptr结果为10。

单链表形参详解

示例:

typedef struct node
{
	int data;//数据域
	struct node * next;//指针域
}Lnode, * SLinkList;
SLinkList Init_List(Lnode *&L)
{
	L = (SLinkList)malloc(sizeof(Lnode));
	L->next = NULL;
	return L;
}

同样的,根据我前面讲的知识,我定义了一个SLinkList 指针型的初始化链表函数 Init_List(),传入的是结构体指针变量L,接下来为L分配内存空间,这里sizeof(Lnode)是计算了结构体Lnode所占内存大小并将此内存分配给L,接下来让初始化L,让其指针域为空。实际上L->data =NULL,L 就是单链表中的头结点。这段代码是没有问题的,但是如果把形参中的Lnode *&L,改为Lnode *L,那么编译器必然会提示我们,取消对NULL指针的使用,这就是为什么我们要加上&的原因,不加&返回的不是我们分配的指针变量L的地址,那这样我们的初始化毫无意义,虽然不报错,但是毫无作用。所以提醒你们写数据结构的时候记住这个小细节,很重要的!

单链表实战案例

完整代码实现

#include<iostream>
using namespace std;
#define SIZE 10
typedef struct node
{
	int data;//数据域
	struct node * next;//指针域

}Lnode, * SLinkList;
SLinkList Init_List(Lnode *&L)
{
	L = (SLinkList)malloc(sizeof(Lnode));
	L->next = NULL;
	return L;
}
SLinkList Creat_List(Lnode* &L,int n)//头插建表
{
	srand((unsigned int)time(NULL));
	SLinkList p = L;
	for (int i = 0; i < n; i++)
	{
		int e = rand() % 20 + 1;
		SLinkList s = (SLinkList)malloc(sizeof(Lnode));
		s->next = p->next;
		p->next = s;
		s->data = e;
	}
	return L;
}
int count_List(Lnode *& L)
{
	int count = 0;
	SLinkList p = L->next;
	while (p)
	{
		count++;
		p = p->next;
	}
	return count;
}
int find_List(SLinkList L,int v)
{
	SLinkList p = L->next;
	int i = 1;
	while (i < v && p->next)
	{
		p = p->next;
		i++;
	}
	return p->data;
}
void display_List(SLinkList L)
{
	SLinkList p = L->next;
	while (p)
	{
		cout << p->data << " ";
		p = p->next;
	}
}
int main()
{
	srand((unsigned int)time(NULL));
	int n = rand()%5 + 5, count = 0, v = 0;
	SLinkList L;
	L = Init_List(L);
	cout << "随机插入元素完成:"<<endl;
	L = Creat_List(L,n);
	count = count_List(L);
	cout << "单链表长度为:" << count << endl;
	cout << "遍历单链表结果为:" << endl;
	display_List(L);
	cout << endl;
	cout << "要查找元素的位置为:"; cin >> v;
	int value = find_List(L, v);
	cout << "查找结果为:" << value << endl;
}

详解头插建表

把头插建表方法复制过来

SLinkList Creat_List(Lnode* &L,int n)//头插建表
{
	srand((unsigned int)time(NULL));
	SLinkList p = L;
	for (int i = 0; i < n; i++)
	{
		int e = rand() % 20 + 1;
		SLinkList s = (SLinkList)malloc(sizeof(Lnode));
		s->next = p->next;
		p->next = s;
		s->data = e;
	}
	return L;
}

这里不用管srand((unsigned int)time(NULL));这段代码是为了产生不同随机数,和我讲的内容没有什么联系;往下看,创建建构体指针变量p并把p设置为头指针:L是头结点,p=L,p指向链表第一个带值结点。进入循环语句,循环语句n我会利用随机数产生;e是1~20范围内随机的一个数值,结构体指针变量s被动态分配内存空间s->next = p>next; p->next = s;s->data = e;这三行代码是头插法的核心。首先待插入原色s指针指向头结点指向的结点,然后头指针指向s,这样链表的链就连好了,最后给s的数据域赋值为e,执行循环语句,这样新插入的结点都会在上一个插入结点的前面,这就是头插法的全部过程。

int count_List(Lnode *& L); 方法对应第一问;

int find_List(SLinkList L,int v);方法对应第二问;

相信认真看完这篇博文的你可以很好理解上面两种方法的含义以及整个源码表达的意思,最后附上运行效果截图:

运行效果

到此这篇关于C语言深入探索之单链表与typedef的用法的文章就介绍到这了,更多相关C语言单链表与typedef内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中typedef的用法以及#define区别详解

    目录 1.简洁定义 2.为已有类型起别名 为字符数组起别名 为指针起别名 3.typedef 和 #define 的区别 总结 1.简洁定义 C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样.而编程中起别名,是为了编程人员编程方便,例如: 定义如下结构体 struct stu { int ID; char name[20]; float score[3]; char *data; }; 要想定义一个结构体变量就得这样写: struct stu Marry://Marry是

  • C语言 超详细模拟实现单链表的基本操作建议收藏

    目录 1 链表的概念及结构 2 链表的分类 3 链表的实现无头+单向+非循环链表增删查改实现 3.1 链表的定义 3.2 链表数据的打印 3.3 链表的尾插 3.4 链表空间的动态申请 3.5 链表的头插 3.6 链表的尾删 3.7 链表的头删 3.8 链表任意位置的前插入 3.9 链表任意位置的后插入 3.10 链表的任意位置的删除 3.11 链表的任意位置的前删除 3.12 链表的任意位置的后删除 3.13 链表的销毁 3.14 链表的总结 1 链表的概念及结构 概念:链表是一种物理存储结构

  • C语言入门学习笔记之typedef简介

    在单片机和操作系统中 typedef 会经常用到,它可以为某一个类型自定义名称.和#define比较类似.但是又有不同的地方. typedef 创建的符号只能用于数据类型,不能用于值.而#define 创建的符号可以用于值. typedef 是由编译器来解释,而不是预处理器. typedef 使用起来更加灵活. 下面使用typedef定义一个数据类型 int main() { typedef unsigned char BYTE; BYTE c = 10; printf("%d \r\n&quo

  • 深入解析C语言中typedef的四个用途

    用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针, 和一个字符变量:以下则可行:typedef char* PCHAR; // 一般用大写PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针虽然:char *pa, *pb; 也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事. 用途二:用在旧

  • C语言 typedef:给类型起一个别名

    C语言允许为一个数据类型起一个新的别名,就像给人起"绰号"一样. 起别名的目的不是为了提高程序运行效率,而是为了编码方便.例如有一个结构体的名字是 stu,要想定义一个结构体变量就得这样写: struct stu stu1; struct 看起来就是多余的,但不写又会报错.如果为 struct stu 起了一个别名 STU,书写起来就简单了: STU stu1; 这种写法更加简练,意义也非常明确,不管是在标准头文件中还是以后的编程实践中,都会大量使用这种别名. 使用关键字 typede

  • ​​​​​​​C语言实现单链表基本操作方法

    目录 存储结构 基本功能 头插法创建单链表 尾插法创建单链表 获取指定位置的元素 在指定位置插入元素 删除指定位置的元素 获取单链表的长度 合并两个非递减的单链表 晴链表 遍历打印单链表 附上完整代码 存储结构 typedef int dataType://爱护据类型 typedef struct Node { DataType data; // 结点数据 struct Node *next; // 指向下一个结点的指针 } Node, *LinkList; 基本功能 头插法创建单链表void

  • C语言数据结构实例讲解单链表的实现

    目录 1.单链表 2.单链表的实现 头文件 函数的实现 (1)打印链表 (2)动态申请结点 (3)尾插 (4)头插 (5)尾删 (6)头删 (7)查找 (8)在pos之前插入 (9)删除pos (10)在pos之后插入 (11)在pos后删除 (12)最后用完记得销毁 3.各功能的测试 这里我们来简单实现单链表的增删查找. 1.单链表 概念:链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 . (链表和我们生活中最接近的就是火车了.) 2.单链

  • C语言实题讲解快速掌握单链表上

    目录 1.移除链表元素 2.反转链表 3.链表的中间节点 4.链表中倒数第k个节点 5.合并两个有序链表 6.链表分割 1.移除链表元素 链接直达: 移除链表元素 题目: 思路: 此题要综合考虑多种情况,常规情况就如同示例1,有多个节点,并且val不连续,但是非常规呢?当val连续呢?当头部就是val呢?所以要分类讨论 常规情况: 需要定义两个指针prev和cur,cur指向第一个数据,prev指向cur的前一个.依次遍历cur指向的数据是否为val,若是,则把prev的下一个节点指向cur的下

  • C语言实题讲解快速掌握单链表下

    目录 1.移除链表元素 2.反转链表 3.链表的中间节点 4.链表中倒数第k个节点 5.合并两个有序链表 6.链表分割 1.移除链表元素 链接直达: 移除链表元素 题目: 思路: 此题要综合考虑多种情况,常规情况就如同示例1,有多个节点,并且val不连续,但是非常规呢?当val连续呢?当头部就是val呢?所以要分类讨论 常规情况: 需要定义两个指针prev和cur,cur指向第一个数据,prev指向cur的前一个.依次遍历cur指向的数据是否为val,若是,则把prev的下一个节点指向cur的下

  • C语言深入探索之单链表与typedef的用法

    目录 前言 详解typedef关键字 含义 具体使用 详解单链表参数形式 指针知识补充 单链表形参详解 单链表实战案例 完整代码实现 详解头插建表 运行效果 前言 昨天博主去本站问答贴子逛了逛,然后发现了好多关于数据结构线性表,具体来说是单链表的问题.有的是没有一点思路,无从下手:有的是看不懂代码,不理解关键字以及被形参的形式气的不行,我总结了一下常见问题来给大家带来干货,到后面还有简单案例来巩固知识,弄透一题胜无脑刷百题,接下来是正文内容. 详解typedef关键字 含义 C语言允许用户使用

  • c语言实现两个单链表的交叉合并方式

    如下所示: #include<stdio.h> #include<stdlib.h> #include<iostream> using namespace std; struct Node { int data; Node *next; }; //初始化 Node *init() { Node *head=new Node; head->next=NULL; return head; } //头插法创建节点 void insetList(Node *head,in

  • C语言创建和操作单链表数据结构的实例教程

    1,为什么要用到链表 数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性.但数组也同样存在一些弊病.如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不同问题有时需要3 0个大小的数组,有时需要5 0个数组的大小,难于统一.我们只能够根据可能的最大需求来定义数组,常常会造成一定存储空间的浪费. 我们希望构造动态的数组,随时可以调整数组的大小,以满足不同问题的需要.链表就是我们需要的动态数组.它是在程序的执行过程中根据需要有数据存储就向系统要求

  • C语言中如何实现单链表删除指定结点

    目录 单链表删除指定结点 链表的删除结点(各种方法) 链表中删除第i个结点 删除与链表中与a相同的结点 删除链表中重复元素 单链表删除指定结点 在单链表中删除指定的结点.这里单链表是用尾插法建立的,因为尾插法输出的顺序与输入的顺序是相同的. #include <bits/stdc++.h> using namespace std; typedef struct node { int data; struct node *next; }no; int main() { no *head,*tai

  • C语言数据结构之顺序表和单链表

    一.顺序表的创建.删除和插入 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> struct sqlist { int date[10]; int length; }; void InitList(sqlist& L) { for (int i = 0;i < 10;i++) { L.date[i] = 0; } L.length = 0; } void charu(sqlist& L) { for (int j =

  • C/C++实现线性单链表的示例代码

    目录 线性单链表简介 C语言实现代码 C++语言实现代码 线性单链表简介 使用链存储结构的线性存储结构为线性单链表,线性存储结构是元素逻辑结构一对一,链存储结构是元素物理结构不连续,线性单链表操作没有限制,线性单链表优点是可以直接插入和删除元素,线性单链表缺点是不可以使用下标获取和修改元素. C语言实现代码 #include<stdio.h>//包含标准输入输出文件 #include<stdlib.h>//包含标准库文件 typedef struct element//元素 { i

  • C语言单链表实现多项式相加

    本文实例为大家分享了C语言单链表实现多项式相加的具体代码,供大家参考,具体内容如下 //多项式的相加和相乘 #include<stdio.h> #include<stdlib.h> #pragma warning(disable:4996)//兼容scanf typedef struct node { int coef; int expon; struct node* link; }Polynode,*Polynomial; Polynomial InsertPolyLinklis

  • Go语言单链表实现方法

    本文实例讲述了Go语言单链表实现方法.分享给大家供大家参考.具体如下: 1. singlechain.go代码如下: 复制代码 代码如下: ////////// //单链表 -- 线性表 package singlechain //定义节点 type Node struct {     Data int     Next *Node } /* * 返回第一个节点 * h 头结点  */ func GetFirst(h *Node) *Node {     if h.Next == nil {  

  • C语言单链表常见操作汇总

    C语言的单链表是常用的数据结构之一,本文总结了单链表的常见操作,实例如下: #include<stdio.h> #include<stdlib.h> //定义单链表结构体 typedef int ElemType; typedef struct Node { ElemType data; struct Node *next; }LNode,*LinkList; //创建单链表 void Build(LinkList L) { int n; LinkList p,q; p=L; pr

随机推荐