六、C语⾔数据结构和算法
(1)数据结构,顾名思义,数据的结构,⽽如何将数据组合成⼀种结构了,C语⾔⾥⽤到了struct结构体类型、union联合体类型、enum 枚举类型这三种。
struct结构体类型,顾名思义,是⼀种结构,⼀种由基本数据类型(int、char、double、float等等)组合⽽成的⼀个整体,⾄于如何组合,很简单。
如:
struct 结构体名字
{
int  mA;
int  mKK;
float  m_Float;
};//不要忘记末尾加分号
结构体名字就是变量名,遵循命名规则,这样就定义了⼀个结构体类型!注意,是定义了⼀种类型!这种类型和基本数据类型是没有任何区别的,都是数据类型!都是可以⽤来定义变量的!
结构体类型定义变量的⽅式:
【struct 结构体名字 变量名;】
这样就定义了⼀个某某结构体的变量了,若是如此:
【struct 结构体名字* 变量名;】
这样就定义了⼀个某某结构体变量的指针了。
注意:C语⾔的结构体类型是【struct 结构体名字】,记住,这是两个单词组合起来作为⼀个类型名称使⽤的!这个的⼀个整体就等价于整型的int这个符号。以后不论任何时候使⽤到结构体类型,都必须是【struct 结构体名字】这种⽅式。c语言struct头文件
如:某某结构体指针类型【struct 结构体名字*】,这⾥多了个*解引⽤运算符,⽤来表⽰指针。
如:
struct myStructName
{
int  mA;
int  mKK;
float  m_Float;
struct myStructName*  next;
};//不要忘记末尾加分号
这⾥在myStructName结构体中定义⼀个myStructName结构体的指针,但注意,这⾥不能定义myStructName结构体的变量,因为myStructName结构体其实还没定义,只是被声明了,只有在分号结束后才定义了myStructName结构体。
⽽且,反证法,若是myStructName结构体内部定义了⼀个myStructName的结构体变量,显然sizeof(struct myStructName)时候,这⾥的sizeof是在编译时候就获得结果⼤⼩的函数,sizeof去获取m
yStructName结构体的⼤⼩,但是myStructName结构体的⾥⾯还有myStructName结构体⼤⼩,怎么办?死循环呗!挂掉了!
⽽若是myStructName结构体⾥⾯定义myStructName结构体指针,不论任何指针都只有32位的,所以sizeof是有效的。
如,定义⼀个链表,显然需要两个结构体,链表描述需要⼀个,链表节点需要⼀个:
struct myListNode
{
struct myListNode* next;        //指向下⼀个节点的指针
struct myListNode* prev;        //指向前⼀个节点的指针
int mData;        //节点存储的数据
};
struct myList
{
struct myListNode*  mHead;        //指向链表头部指针
struct myListNode*  mTail;            //指向链表尾部指针
int  m_size;    //链表的⼤⼩
};
这两个结构体定义就能够组合成⼀个链表,若是加上⼀些操作链表的函数,就成为了⼀个数据结构。简单吧!⽼婆。
注:链表不可能是连续分配的内存,所以链表使⽤的内存必须是malloc分配的堆内存,也就是由程序员⾃⼰管理,只要能够索引到对应的内存指针,就能获取对应的数据。
注:链表,⽣动地来说,就像⽆数条链⼦链接起来的⼀块块内存,可能这块内存在这⾥,可能那块内存在那⾥,内存位置是不确定的,但所有的内存必然有且⾄少有⼀个指针指向它!⽽这些内存就能够存放数据了。
(2)union联合体
联合体,顾名思义是联合起来的⼀个整体,如何联合起来呢?就是内存空间联合起来!也就是⼀段内存空间,可以存放联合体中所定义的任何类型数据。
注:联合体的声明和定义和结构体的声明定义是⼀样的,但是对联合体的解释是不同的。
如:
union 联合体名字
{
int  mA;
short  mB;
char  mC;
double mD;
};//不要忘记分号
这个联合体的内存只会分配其成员中,占⽤内存最⼤的内存数量的内存空间!这⾥是double占⽤空间最⼤,有8个字节,所以这个联合体只占8个字节!
⽽且联合体的值,每⼀次对其成员进⾏赋值,都会改变所有成员的值,如:
【union 联合体名字 myUnion; myUnion.mA = 10; myUnion.mB = 20;】
这⾥在第⼀次赋值为10之后,不论是mB、mC或mD都是10,直到第⼆次赋值为20,那么不论是mA、mB、mC或mD都是20。也就是同⼀时间,联合体只能存储⼀个值!
(3)enum枚举类型
枚举类型,顾名思义,枚举,就是所有值都列举出来!所以其声明定义如下:
enum
{
ENUM_Name1,
ENUM_Name2,
ENUM_Name3,
};
枚举类型⾥的成员必定是⼀个名字,且这个名字代表着某个值,若是没有被赋值,就会默认赋值给前⼀个名字数值的加⼀,如第⼀个ENUM_Name1没有赋值,默认值为0,ENUM_Name2就是“0+1”,ENUM_Name3就是“1+1”,这⾥的ENUM_Name2和
ENUM_Name3并不是简单的1和2,其值和名字是作为⼀个唯⼀标识,作为枚举的⼀个成员。
这⾥的值可以重复的,如:
enum
{
ENUM_Name1 = 1,
ENUM_Name2,
ENUM_Name3 = 2,
};
很显然,ENUM_Name2的值就是“1+1”,看起来字⾯上是2,且和ENUM_Name3重复,但真正的值并不是2,⽽是“1+1”。
注:枚举类型⾥的成员都是明确规定的值,这些值不管字⾯上表⽰如何,都绝对不会是相同的。⽽且枚举类型的成员的类型是独有的,和其他基本数据类型不同。
(4)算法,顾名思义,是计算的⽅法,计算的⽅式⽅案,怎么计算就会有怎么样的⽅法,计算的过程就是这种⽅法,所以,计算的过程和得到结果就叫算法!
如:【c = a+b;】这句语句也是算法,计算过程是a+b,计算结果是c。
如:使⽤for循环遍历⼀个列表,这也是算法,计算过程是使⽤for循环,计算结果就是“遍历了列表”
如:⽤⼆分搜索的⽅法搜索⼀组数据,这也是算法,计算过程是使⽤⼆分搜索,搜到的结果是所需要的某个值。
算法,其实任何语句都是⼀个算法,只是有难易的区分⽽已。
⼀般常⽤的算法有:⽤于排序的冒泡排序、插⼊排序、快速排序这些,⽤于搜索某个值的⼆分搜索、递归搜索、哈希搜索、⼆叉树等等
c语⾔标准库提供有⼀些算法函数,如快速排序算法qsort;
void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *));
base表⽰传⼊的数组,
nelem表⽰数组⼤⼩,
width表⽰数组每个数据所占的字节数
fcmp是⽤于⽐较的函数指针,⽤于确定排序顺序。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。