国嵌数据结构视频 学习笔记
专题1.内行看门道.
第一节.1进阶高手的大门_
1数据结构的教学目标.
理论与实践相结合,数据结构比较难,
数据结构分成专题的形式,计算机现在是应用.
不是搞理论的.
2进阶高手的大门?
什么是高手?语言是要靠应用的,学了就要用,
学了不用就是废物.计算机是用来处理数据,计算.
3. 程序的灵魂---算法.
审批程序的灵魂.
什么才是好程序,
1.可读性,
2.性能比,
4. 问:什么是高手?学习了C语言,还是写不出程序,为什么?
因为你还没理解程序.
问题1:为什么有各种各样的程序存在?
网上有大把的程序例子,播放程序,聊天程序,有那么多程序,
为什么还有人不断继续开发新的程序, 就播放程序,
百度开发,QQ在出,讯雷也在出, 为什么他们还要出?
为什么有那么的程序存在?那就要了解程序的本质.
这是什么问题啊,没有逻辑.
5:程序的本质是什么?
答: 1.程序的本质,就是为了解决实际问题而存在的.
从本质上而言,程序是解决问题的步骤描述.
6.C语言从main开始运行的,一句一句代码运行.
7.怎么把大象放在冰箱.
1.打开冰箱门. Elephan * e = getElep();
2.把大象放进去. int f = open("fridga");
3.关上冰箱门. put(f,e); close(f);
这就是解决问题的步骤.问题的解决步骤,从而导出程序的逻辑.
如果学了C语言,写不出程序,那是因为你遇到实现的问题大小了.
你上机,练习的时间太少,
开发程序的前提条件,深入分析遇到的问题.导出程序逻辑.
所先我们首先理解实际问题.
a. 确认问题类型.
如:数值计划,求最小值个数
b. 确认求解的步骤.
如:打开文件,读数据,关闭文件,计算和.
附:如何判断求解步骤的好坏.
7.
在生活中解决一个问题的方法,往往不只一种.
所以通过程序去求解的问题的答案不只一种,
我们如何判断求解步骤的好坏.
解决方法的对比.
求 1+2+....n的和.
三种方法:
1.方法1. 先申请N个空间,把这N个数放进去,然后N个数值 .
2.方法2. 进行使用for循环累加.
3.方法3. 直接使用数学公式. (1+n)*(n/2);
使用方法1的人是比较死板的人.
使用方法2的人是比较平常的人.
使用方法3的人是thinkabout的人.善于思考的人.
8.程序评监初探.
81.尽量少的内存空间解决问题.
82.尽量少的步骤解决问题.
优秀的开发者需要追求代码的高"性价比"
但是这也不是绝对了,有时候在那个提高代码的可读性的情况下
会牺牲程序的空间,与步骤.
9.小结:
91.程序是为了具体问题而存在的.
92.程序需要围绕问题的解决进行设计
93.同一个问题可以有多种解决方法.
10 是否有可量化的方法判断程序的好坏?
有没有?
10 如果提高写程序的能力?
如果去判断一个程序的好坏?
最后一句,程序一定要围绕问题而且设计.
第2节.数据的艺术.
1.数据的起源.
计算机一开始是解决数值计算的问题.
后来发展解决生活中的问题.
现实生活中的问题涉及不同个体间的复杂联系.
需要在计算机程序中描述生活中个体间的联系.
数据结构主要研究非数值计算程序问题中的操作对象以及它们
之间的关系.
一句话,数据结构是描述操作对象之间的关系的一门学科.
我们如何理解数据结构的数据了?
关键的概念.
1. 数据 = 程序的操作对象,用于描述客观的事物
2. 数据的特点:
可以输入到计算机,可以被计算机处理.
数据是一个抽象的开概念,将其进行分类后得到程序设计语言中的类型
如:int,float,char等等.
数据结构的数据分类?分什么类? int,char ,float???
3数据元素 -- 组成数据的基本单位.
数据项----个数据元素由若干个数据项组成.
4.数据对象 -- 性质相同的数据元素的集合.
5.数据元素之间不是独立,存在的特点的关系,这是关系即结构.
6.数据结构指数据对象中数据元素之间的关系.
如:数组中各个元素之间存在固定的线性关系.
编写一个好程序之前,必须分析待处理问题中各个对象的特征,以及对象
之间的关系.
数组就是一种数据结构,一种线性的数据结构.
在用却不知道.百姓日用而不知.
数据结构就是研究数据之间的关系.
逻辑结构
集合结构: 数据元素之间没有特别的关系,ji同属相同集合.
线性关系: 数据元素之间是一对一的关系. 如:数组
树形结构: 数据元素之间存在一对多的层次的关系.
图形结构: 数据元素之间是多对多的关系.(还是有用的,比较腾讯的好友推算功能,玩游戏的路径寻找。)
一个图片来表示:
物理结构: 逻辑结构在计算机中的存储形式
顺序存储结构: 将数据存储在地址连续的存储单元里.(对应线性存储)
链式存储结构: 将数据存储在任意存储单元里,
通过保存地址的方式找到相关取的数据元素.(对应树图的存储)
小结
数据
数据对象 数据对象
数据元素 数据元素 数据元素 数据元素
数据结构是相互之间存在一种或多种
特定关系的数据元素的集合.
按照视点的不同,数据结构可以分成
逻辑结构(集合,线性,树形,图形)
物理结构( 顺序,链式结构)
第3节,程序的灵魂-算法.
1.算法与数据结构有什么关系?
要搞清楚这个问题,
程序是否越短越好?是否别人看不懂就证明自己很厉害.
不是
数据结构与算法.
a.数据结构只是静态的描述了数据元素之间的关系.
b.高效的程序需要在数据结构的基础上设计和选择算法.
高效的程序 a.恰当的数据结构
b.合适的算法
数据结构与算法是两门课程,
本课程主要是讲数据结构,但是算法与数据结构是
联系在一起,再能更加好解决问题.
现在是重点是数据结构,引进算法,其实两者不可分开 的.
但是一起讲,内容太多了,再加上算法涉及的
知识太多,涉及一些数学方面的知道 .
算法的定义
a.算法是特点问题求解步骤的描述.
b.计算机中表现为指令的有限序列.
算法是独立存在的一种解决问题的方法和思想.
对于算法而言,语言并不重要,重要的是思想.
语言重要吗?语言也是重要,适合,每种语言都有自己的特点.
针对于应用,开发linux驱动,C语言比较适合,但是开发网站就不适合了.
算法的特征
1. 输入:具有0个或多个输入
2.输出:算法到少有1个或多个输出.
3.有穷性: 算法在有限的步骤之后会自动解除而不会无限循环.
4.确定性:算法中的每一步都有确定的含义,不会出现二义性.
5.可行性:算法的每一步都是可行的.
程序包含了各种算法,但是程序不是算法,这些概念可以理解,也可以不理解.
算法设计的准则
1.正确性
a:算法对于合法数据能够得到满足要求的结果.
b:算法能够处理非法输入,并得到合理的结果.
c:算法对于边界数据和压力数据都能得到满足要求的结构.
注意:正确性是算法是需要满足的基本的准则,但是作为计算机程序,
不可能无限制的满足这条准则.
例如,我们有一个排序法,我输入1000亿个数据去排序,就出问题了.
2.可读性: 算法要方便阅读,理解和交流
3.健壮性:算法不应该产生莫名其妙的结果.
4.高性价比:利用最少的时间和资源得到满足要求的结果.
注意:算法可读性是最容易被忽视,然而,程序是写给人看的,而不是计算机.
小结
1:算法是 为了解决实际问题而设计的.
2.数据结构是算法需要处理的问题载体.
3.数据结构与算法相缚相成的.
程序 = 数据结构 + 算法.
第4集 审批程序的灵魂.
算法效率的度量
1.事后统计法:比较不同算法对一组输入数据的运行处理时间
2.缺陷:为了获得不同算法的运行时间必须编写相应程序
运行时间严重依赖硬件以及运行时的环境因素.
算法的测试数据的选取相当困难.
事后统计法虽然直观,但是实施困难且缺陷多,一般不于考虑.
3.事前分析估算:依据统计的方法对算法效率进行估算.
4.影响算法效率的主要因素
算法采用的策略和方法
问题的输入规模
编译器所产生的代码
计算机执行速度.
5.算法的效率 与 算法本身与问题规模相关.
---算法本身就是解题步骤 计算机语句
---问题规模就是N
算法的效率的度量,
简单的估算,计算执行的指令.
关键部分,操作数量为n*n.
随意问题规模n的增大,它们操作数量的差异会越来越大,因
此际算法在时间效率上差异也会变得非常明显.
算法效率的度量.
判断一个算法的效率时,往往只需要关注操作数量的最高次项
其它次要项和常数项可以忽略.
算法效率的度量
大O表示法
1. 算法效率严重依赖操作数量
2. 在判断时首先关注操作数量的最高项.
3. 操作数量的估估算可以作为时间复杂度的估算.
O(5) =O(1)
O(2N+1) = O(2N)=O(N)
O(NN+N+1)= O(NN)
O(3NNN+1)=O(3NNN)=O(NNN)
算法效率的度量
常见时间复杂度类型
常数阶
线性阶
平方阶
对数阶
nlogn阶
立方阶
指数阶
最坏与最好
在没有特殊说明时,,我们 我们所分析的算法的时
间复杂度都是指最坏时间复杂度。
算法空间复杂度.
算法的空间复杂度通过计算算法的存储空间来实现
s(n) =O(f(n));
空间与时间的策略
多数情况下,算法执行所用的时候更加令人关注.
如果有毕业,可以过过增加空间复杂度来降低时间复杂性.
同理,也可以过过增加时间复杂度来降低空间复杂度.
在实现算法时,
需要分析具体问题对执行时间和空间的要求..
专题二 .线性表.
第一节:线性表的本质.
1.
线性表的定义
a.线性表(List)是0个或多个数据元素的集合.
b.线性表中的数据元素之间是有顺序的.
c.线性表的数据元素是有限的.
d.线性表中的数据元素的类型必须相同.
定义: 线性表是具有相同类型的N(N>0)个数据元素的有限序列.
(a1,a2,,,,,,an) ai是表项,n 是表长度.
性质:
a0是线性表的第一个元素,只有一个后继.
an为线性表的最后一个元素,只有一个前驱.
除了a0和an外的其它的元素ai, 有前驱后继.
线性表能够逐项访问和顺序存取.
小结:
线性表是数据元素的有序并且有限的集合
线性表中的数据元素必须是类型相同的
线性表可用于描述队列类型关系的问题.
一年的12个月构成了一种线性表.
第二节,线性表的相关操作.
主要内容.
1.线性表的操作.
a. 创建线性表
b. 销毁线性表
c.清空线性表
d.将元素插入线性表
e.将元素从线性表中删除
g.获取线性表中的某个元素的位置.
h.获取线性表的长度.
线性表操作的实现
线性表在程序中表现为一种特殊的数据类型
线性表的操作在程序中表现为一组函数
List
List * List_Creat();
void List_Destroy(List * list);
void List_Clear(List *list);
int List_Length(List* list);
ListNode* List_Delete(List* list, int pos);
ListNode* List_Get(List* list, int pos);
int List_Insert(List* list, ListNode* node, int pos);
用C语言描述线性表E:\数据结构(国嵌)\lxmcode\TestList
小结:
线性表在程序中表现为一种特殊的数据类型
线性表的操作则表现为一组相关的函数.
问题:线性表的各个函数如何实现?
有几种线性表的实现方式?
每种实现方式的优缺点是什么?
第三节 线性的顺序存储结构
本节主要内容.
1.顺序存储结构定义
线性表的顺序存储结构,,指的是用一段 指的是用一段
地址连续的存储单元依次存储线性表的
数据元素。
2.顺序存储结构
在C语言中可以用一维数组来实现顺序存储结构
存储空间的起始位置::数组 数组node
线性表的最大容量::数组长度 数组长度MAXSIZE
线性表的当前长度:length
#define MAXSIZE 20
typedef struct _tag_List{
char node[MAXSIZE];
int length;
}List;
3.顺序存储结构的操作
a.获取元素操作.
判断线性表是否合法
判断位置是否合法.
直接通过数组下标的方式获取元素.
char Get(List * list, int pos){
char ret = -1;
//1.判断线性表是否合法
//.判断位置是否合法
if( (list !=NULL) && (0 <= pos) && (pos < list->length) )
{
//获取元素
ret = list->node[pos];
}
return ret;
}
b. 插入元素算法
判断线性表是否合法
判断插入位置是否合法
把最后一个元素到插入位置的元素后移一个位置
将新元素插入
线性表长度加1
int Insert(List * list ,char c , int pos)
{
//1.判断线性表是否合法
int ret = (list!=NULL);
int i = 0;
//2.判断插入位置是否合法
ret = ret && (list->length +1 <= MAXSIZE);
ret = ret &&(0 <= pos);
if(ret)
{
if(pos >= list->lentgh)
{
pos = list->length;
}
//3.从最后一个元素开始到第pos个位置
//分别将他们都向后移动一个位置
for(i=list->length; i>pos; i--)
{
list->node[i] = list->node[i-1];
}
//4.将新元素插入
list->node[i] = c;
list->length++;
}
return ret;
}
C 删除元素算法
判断线性表是否合法
判断删除位置是否合法
将元素取出
将删除位置后的元素分别向前移动一个位置
线性表长度减1
char Delete(List *list, int pos)
{
char ret = -1;
int i = 0;
//1.判断线性表是否合法
//2.判断删除位置是否合法
if( (list!=NULL) && (0 <= pos) && (pos < list->length) )
{
//获取删除元素
ret = list->node[pos];
for(int i = pos + 1; i <list->length; i++)
{
//4.把删除位置pos后的元素分别向前移动一个位置
list ->node[i-1] = list->node[i];
}
//5.长度减1
list->length--;
}
return ret;
}
创建可复用的线性表:
代码如下:
#include <stdio.h>
#include <malloc.h>
#include "SeqList.h"
typedef unsigned int TSeqListNode;
typedef struct _tag_SeqList
{
int capacity;
int length;
TSeqListNode* node;
} TSeqList;
SeqList* SeqList_Create(int capacity) // O(1)
{
TSeqList* ret = NULL;
if( capacity >= 0 )
{
ret = (TSeqList*)malloc(sizeof(TSeqList) + sizeof(TSeqListNode) * capacity);
}
if( ret != NULL )
{
ret->capacity = capacity;
ret->length = 0;
ret->node = (TSeqListNode*)(ret + 1);
}
return ret;
}
void SeqList_Destroy(SeqList* list) // O(1)
{
free(list);
}
void SeqList_Clear(SeqList* list) // O(1)
{
TSeqList* sList = (TSeqList*)list;
if( sList != NULL )
{
sList->length = 0;
}
}
int SeqList_Length(SeqList* list) // O(1)
{
TSeqList* sList = (TSeqList*)list;
int ret = -1;
if( sList != NULL )
{
ret = sList->length;
}
return ret;
}
int SeqList_Capacity(SeqList* list) // O(1)
{
TSeqList* sList = (TSeqList*)list;
int ret = -1;
if( sList != NULL )
{
ret = sList->capacity;
}
return ret;
}
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) // O(n)
{
TSeqList* sList = (TSeqList*)list;
int ret = (sList != NULL);
int i = 0;
ret = ret && (sList->length + 1 <= sList->capacity);
ret = ret && (0 <= pos);
if( ret )
{
if( pos >= sList->length )
{
pos = sList->length;
}
for(i=sList->length; i>pos; i--)
{
sList->node[i] = sList->node[i-1];
}
sList->node[i] = (TSeqListNode)node;
sList->length++;
}
return ret;
}
SeqListNode* SeqList_Get(SeqList* list, int pos) // O(1)
{
TSeqList* sList = (TSeqList*)list;
SeqListNode* ret = NULL;
if( (sList != NULL) && (0 <= pos) && (pos <= sList->length) )
{
ret = (SeqListNode*)(sList->node[pos]);
}
return ret;
}
SeqListNode* SeqList_Delete(SeqList* list, int pos) // O(n)
{
TSeqList* sList = (TSeqList*)list;
SeqListNode* ret = SeqList_Get(list, pos);
int i = 0;
if( ret != NULL )
{
for(i=pos+1; i<sList->length; i++)
{
sList->node[i-1] = sList->node[i];
}
sList->length--;
}
return ret;
}
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
typedef void SeqList;
typedef void SeqListNode;
SeqList* SeqList_Create(int capacity);
void SeqList_Destroy(SeqList* list);
void SeqList_Clear(SeqList* list);
int SeqList_Length(SeqList* list);
int SeqList_Capacity(SeqList* list);
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
SeqListNode* SeqList_Get(SeqList* list, int pos);
SeqListNode* SeqList_Delete(SeqList* list, int pos);
#endif
#include <stdio.h>
#include <stdlib.h>
#include "SeqList.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[])
{
SeqList* list = SeqList_Create(5);
int i = 0;
int j = 1;
int k = 2;
int x = 3;
int y = 4;
int z = 5;
int index = 0;
SeqList_Insert(list, &i, 0);
SeqList_Insert(list, &j, 0);
SeqList_Insert(list, &k, 0);
SeqList_Insert(list, &x, 0);
SeqList_Insert(list, &y, 0);
SeqList_Insert(list, &z, 0);
for(index=0; index<SeqList_Length(list); index++)
{
int* p = (int*)SeqList_Get(list, index);
printf("%d\n", *p);
}
printf("\n");
while( SeqList_Length(list) > 0 )
{
int* p = (int*)SeqList_Delete(list, 0);
printf("%d\n", *p);
}
SeqList_Destroy(list);
return 0;
}
小结:
优点:
无需要国线性表中的逻辑关系增加额外的空间.
可以快速的获取表中合法位置的元素.
缺点:
插入和删除操作需要移动大量元素.
当线性表长度变化输大时难以确定存储空间.
第4小节 线性表的链式存储结构.
1. 问题: 顺序表的思考.
顺序表的最大问题是插入和删除需要移动大量的元素.如何解决.
2. 链式存储结构的定义.
为了表示每个数据元素与其直接后继元素之间的
逻辑关系,,每个元素除了存储本身的信息外 每个元素除了存储本身的信息外,,还还
需要存储指示其直接后继的信息。
3. 链式存储逻辑结构
n个结点链接成一个链式线性表的结构叫做链表,
当每个结点中只包含一个指针域时,,叫做单链表 叫做单链表.
4. 链表的基本概念
41表头结点
链表中的第一个结点,,包含指向第一个数据元素的指针以及 包含指向第一个数据元素的指针以及
链表自身的一些信息
42数据结点
链表中代表数据元素的结点,,包含指向下一个数据元素的指 包含指向下一个数据元素的指
针和数据元素的信息
43尾结点
链表中的最后一个数据结点,,其下一元素指针为空 其下一元素指针为空,,表示无 表示无
后继
5 链式存储结构
51:在C语言中可以用结构体来定义链表中的指针域
52:链表中的表头结点也可以用结构体实现
code:
结点指针域定义
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode
{
LinkListNode * next;
};
头结点定义
typedef struct _tag_LinkList
{
LinkListNode header;
int length;
}TLinkList;
数据元素定义示例
struct Value
{
LinkListNode header;
int v;
}
53获取第pos个元素操作
判断线性表是否合法
判断位置是否合法
由表头开始通过n ext指针移动pos次后,,当前元素的 当前元素的n ext指
针即指向要获取的元素
LinkListNode * current = (LinkListNode *) list;
for(i=0; i<pos; i++)
{
current = current->next;
}
ret = current->next;
54插入元素操作
插入元素到位置pos的算法
判断线性表是否合法
判断插入位置是否合法
由表头开始通过n ext指针移动pos次后,,当前元素的 当前元素的n ext指
针即指向要插入的位置
将新元素插入
线性表长度加1
LinkListNode * current = (LinkListNode *) list;
for(i = 0;(i < pos) && (current->netx != NULL); i++)
{
current = current->netx;
}
node->next = current->next;
current->netx = node;
sList->length++;
55 删除元素操作
删除第pos个元素的算法
判断线性表是否合法
判断插入位置是否合法
获取第pos个元素
将第pos个元素从链表中删除
线性表长度减1
创建可复用单链表
code
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
typedef void LinkList;
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode
{
LinkListNode* next;
};
LinkList* LinkList_Create();
void LinkList_Destroy(LinkList* list);
void LinkList_Clear(LinkList* list);
int LinkList_Length(LinkList* list);
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
LinkListNode* LinkList_Get(LinkList* list, int pos);
LinkListNode* LinkList_Delete(LinkList* list, int pos);
#endif
#include <stdio.h>
#include <malloc.h>
#include "LinkList.h"
typedef struct _tag_LinkList
{
LinkListNode header;
int length;
} TLinkList;
LinkList* LinkList_Create() // O(1)
{
TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList));
if( ret != NULL )
{
ret->length = 0;
ret->header.next = NULL;
}
return ret;
}
void LinkList_Destroy(LinkList* list) // O(1)
{
free(list);
}
void LinkList_Clear(LinkList* list) // O(1)
{
TLinkList* sList = (TLinkList*)list;
if( sList != NULL )
{
sList->length = 0;
sList->header.next = NULL;
}
}
int LinkList_Length(LinkList* list) // O(1)
{
TLinkList* sList = (TLinkList*)list;
int ret = -1;
if( sList != NULL )
{
ret = sList->length;
}
return ret;
}
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) // O(n)
{
TLinkList* sList = (TLinkList*)list;
int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
int i = 0;
if( ret )
{
LinkListNode* current = (LinkListNode*)sList;
for(i=0; (i<pos) && (current->next != NULL); i++)
{
current = current->next;
}
node->next = current->next;
current->next = node;
sList->length++;
}
return ret;
}
LinkListNode* LinkList_Get(LinkList* list, int pos) // O(n)
{
TLinkList* sList = (TLinkList*)list;
LinkListNode* ret = NULL;
int i = 0;
if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
{
LinkListNode* current = (LinkListNode*)sList;
for(i=0; i<pos; i++)
{
current = current->next;
}
ret = current->next;
}
return ret;
}
LinkListNode* LinkList_Delete(LinkList* list, int pos) // O(n)
{
TLinkList* sList = (TLinkList*)list;
LinkListNode* ret = NULL;
int i = 0;
if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
{
LinkListNode* current = (LinkListNode*)sList;
for(i=0; i<pos; i++)
{
current = current->next;
}
ret = current->next;
current->next = ret->next;
sList->length--;
}
return ret;
}
#include <stdio.h>
#include <stdlib.h>
#include "LinkList.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Value
{
LinkListNode header;
int v;
};
int main(int argc, char *argv[])
{
int i = 0;
LinkList* list = LinkList_Create();
struct Value v1;
struct Value v2;
struct Value v3;
struct Value v4;
struct Value v5;
v1.v = 1;
v2.v = 2;
v3.v = 3;
v4.v = 4;
v5.v = 5;
LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list));
LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list));
LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list));
LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list));
LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list));
for(i=0; i<LinkList_Length(list); i++)
{
struct Value* pv = (struct Value*)LinkList_Get(list, i);
printf("%d\n", pv->v);
}
while( LinkList_Length(list) > 0 )
{
struct Value* pv = (struct Value*)LinkList_Delete(list, 0);
printf("%d\n", pv->v);
}
LinkList_Destroy(list);
while(1);
return 0;
}
优点:
无需一次性定制链表的容量
插入和删除操作无需移动数据元素
缺点:
数据元素必须保存后继元素的位置信息
获取指定数据的元素操作需要顺序访问之前的元素
顺序表的实现中为什么保存的是具体数据元
素的地址??而保存的地址存放在 而保存的地址存放在unsigned
int中中,,,而不是具体的指针类型中 而不是具体的指针类型中??为什么不 为什么不
是void*呢呢?
以下关于链式存储结构的叙述中正确的是
A. 链式存储结构不是顺序存取结构
B. 逻辑上相邻的结点物理上必相邻
C. 可以通过计算直接确定第 i个元素 个元素
D. 插入和删除操作方便,,不必移动其它结点
在单链表的实现和应用中,,还有一种无表头 还有一种无表头
结点的单链表。。根据我们列出的操作 根据我们列出的操作,,编程 编程
实现这种无表头结点的单链表,,并对比表头 并对比表头
实现方式和无表头实现方式哪种更好。
为我们实现的顺序表和单链表添加一个反转操
作作。。。这个操作使得链表中的次序反转 这个操作使得链表中的次序反转,,即第一 即第一
个元素变为最后一个元素,,第二个元素变为倒 第二个元素变为倒
数第二个元素。。。如如:::abcd abcd abcd反转的结果为 反转的结果为
dcba dcba。 。
要求时间复杂度达到O(n)。
SeqList_Reverse(SeqList* list);
LinkList_Reverse(LinkList* list);