- 数据的存储结构/物理结构
– 数据结构在计算机中的表示(或映像),
顺序映像:顺序存储结构
非顺序映像:链式存储结构 ,如,线性表有顺序表和链表两种物理存储方式
– 它可以借助于具体某程序语言中的“数据类型” 来定义它。也可 采用typedef将类型名重命名,以增加代码的可读性
int Sqlist[100];顺序表数据存储结构的实现,描述了100个int型变量组成的集合,且隐含着可利用下标[]来描述两个int型变量间的联系
struct Node{
int data;
struct Node *next };
Typedef struct Node *Link;
Link head;单链表数据存储结构的实现,隐含着可利用指针next来描述两个 struct Node类型的变量之间的联系
- 总结
什么时候需要用到数据结构?
– 操作对象为:取值为同种类型的很多数据,且这些数据间存在某种关系或者某些共性操作
若需要用到DS,那什么时候可以使用线性结构?
– 被操作的数据之间没有天然的一对多和多对多的关系
– 对已存储的数据进行处理时,处理顺序有明显的唯一的先后次序关系
若采用线性结构,具体该使用哪种存储结构?(只讨论顺序表和链表)
– 取决于数据处理时的最频繁操作,为静态操作,还是动态操作?
- 顺序表的静态定义:利用数组
方案一: int Sqlist[100];
方案二: #define List_Size 100 /*分配空间的大小*/
int Sqlist[List_Size ];
方案三:(通用性最强,类似STL:vector) #define List_Size 100/*分配空间的大小*/
Typedef Struct{
int elem[List_Size ]; /*存储空间*/
int len; /*实际长度*/
}SqList_static;
该结构比较机械,分配的内存空间大小固定。List_Size 过小,会导致顺序表上溢,List_Size 过大,会导致空间利用率不高。在编译的时候,系统在函数栈中分配连续的内存空间。当静态顺序表所在的函数执行完毕后, 由系统来回收所开辟的内存空间。 程序运行时,出现上溢问题,将没法修补 。
- 顺序表的动态定义:利用指针
#define List_Size 100 /*分配空间的大小*/
typedef struct{
int *elem; /*顺序表的存储空间*/
int len; /*实际长度*/
int ListSize ; /*当前分配的空间大小*/
} Sqlist;
Int InitSqList(SqList *L)//构造一个空的顺序表L {
L->elem=(int *) malloc(List_Size *sizeof(int));
if (L->elem==NULL)
exit(EXIT_FAILURE);
L->len=0;
L->ListSize =List_Size;
return 1; }
- 单链表定义
struct Node{
int data;
struct Node *next
};
Typedef struct Node *Link;
Link head;
无头结点的单链表
– 头指针为L,则空表时,L == NULL
– 由于第一个结点无前驱结点,所以只能通过某指针变量来指向,如L
有头结点的单链表
– 空表时,L指向一结点(称为头结点),该结点的数据域可以不存储信息,也可存储如表长等的附加信息,结点的指针域存放NULL,即L->next == NULL。
– 第一个结点和其余结点均可统一表示为其直接前驱结 点的next域所指向的结点,即……->next。
- 顺序表的延伸:位向量/位图
什么是位向量?示例:{0,1,2,20,32}用位向量存储为33bit