使用头插法建立单链表:
LinkList Lisyt_HeadInsert(LinkList &L){
LNode *s;int x;
L=(LNode*)malloc(sizeof(LNode));
L->next=NULL;
scanf("%d",&x);
while(x!=9999){
s=(LNode*)malloc(sizeof(LNode)) //后续有解答
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
在 C 语言中,“s=(LNode*) malloc (sizeof (LNode))” 语句的含义如下:
malloc(sizeof(LNode))
:malloc
是一个标准库函数,用于在堆上动态分配一块指定大小的内存空间。sizeof(LNode)
表示计算类型LNode
所占用的字节数,这里就是请求分配一块足够容纳一个LNode
类型对象的内存空间。(LNode*)
:这是一个强制类型转换,将malloc
返回的通用指针类型void*
转换为指向LNode
类型的指针。这样做是为了确保后续可以通过这个指针正确地访问和操作LNode
类型的对象。- 最后将分配的内存地址赋值给指针
s
,此时s
就指向了一块新分配的内存空间,可以用于存储一个LNode
类型的对象。
通过这条语句,可以在程序运行时根据需要动态地为LNode
类型的对象分配内存,而不是在编译时确定固定的内存分配。这在处理可变长度的数据结构或需要动态创建对象的场景中非常有用。需要注意的是,使用malloc
分配的内存需要在适当的时候使用free
函数进行释放,以避免内存泄漏。
顺序存储方式只能用于存储线性结构吗?
顺序存储方式并非只能用于存储线性结构。
顺序存储方式是把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,通常可以用数组来实现。
对于线性结构来说,顺序存储方式确实很常见且直观,比如线性表、栈、队列等。
然而,对于一些非线性结构也可以采用顺序存储方式来进行一定程度的表示。例如二叉树的顺序存储,完全二叉树可以较为方便地用顺序存储方式实现,按照层次遍历的顺序将节点依次存放在数组中,对于不是完全二叉树的情况,可以通过补充空位的方式转化为完全二叉树后进行存储。此外,图的邻接矩阵存储方式也可以看作是一种广义的顺序存储,它是用二维数组来存储图中顶点之间的关系。
所以,顺序存储方式并不局限于存储线性结构。
使用链式存储结构时,结点内的存储单元地址一定是连续的
节点内的存储空间要存储数据与指针,一定要连续
数组排序的最好时间复杂度为O(
)
常见的渐进时间复杂度从低到高的大致顺序
- O(1):常数时间复杂度。无论输入数据规模多大,执行时间都是恒定的。例如访问数组中的特定元素(已知索引)。
- O(
):对数时间复杂度。随着输入数据规模的增大,执行时间以对数方式增长。例如在有序数组中进行二分查找。
- O(n):线性时间复杂度。执行时间与输入数据规模呈线性关系。例如遍历一个数组。
- O(
):常见于高效的排序算法(如快速排序、归并排序、堆排序在平均情况下)。
- O(
):平方时间复杂度。例如冒泡排序、选择排序、插入排序在最坏情况下的时间复杂度。
- O(
):立方时间复杂度。某些算法在处理特定问题时可能出现,一般效率较低。
- O(
):指数时间复杂度。随着输入规模的增长,执行时间呈指数级增长,一般只适用于非常小的输入规模。例如某些暴力搜索算法。
- O(
!):阶乘时间复杂度。增长速度极快,一般只有非常小的输入规模才能在可接受的时间内解决问题。例如全排列问题的暴力解法。
- O(
)
单链表尾结点操作的效率问题
单链表中的尾结点的next域在尾结点中,有关于尾结点删除和与其他链表连接时,需要遍历一遍链表来找到尾结点;