数据结构
一、数据结构分类
-
概念
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。在我们的程序中有着很重要的运用,所以有人说:程序 = 数据结构 + 算法。
算法:描述逻辑
数据结构:描述数据如何存取、操作,数据与数据之间的关系,可以理解为管理数据。
我们重点是要学习他是怎么使用,能在我们的程序中起到怎样的作用。像现在很多国内的书,几乎整本书都在介绍这个东西的起源,介绍这个东西是什么,能在我们的生活起到什么作用,有什么么应用等等,这样的内容基本都能占到整本书的三分之一左右,而对于技术细节不分,基本上都是走马观花似的一带而过。不信,你随便打开一本国产技术类的书,节本上前三章都是介绍这类东西的,尤其是市面上面一些大学出的教材书。不是说不好,但既然作为技术类的书总的分清主次吧,又不是文学历史书。不过,也可以理解,想想你的本科毕业论文的研究背景或者说是研究意义花了多少篇幅。好啦,废话了这么多,其实就是想说,对于一门技术,我们需要重点掌握的其实就是它的使用规则。
-
数据结构的分类
逻辑结构:
-
集合
集合结构中的数据元素处除了同属于一个集合外,他们之间没有其他的关系。每个数据元素是平等的。
-
线性结构
线性结构中数据元素之间是一对一的关系。如图:
-
树形结构
树形结构中,数据元素之间存在一对多的层次关系。
-
图形结构
在图形结构中,数据元素之间是多对多的关系。
可以得出结论,各类型的数据结构的复杂度关系为:
集合 < 线性结构 < 树形结构 < 图形结构
按存储结构分类:
顺序存储结构
链式存储结构
索引存储结构
散列存储结构
存储结构:数据的逻辑结构在计算机存储空间的存放形式。
-
顺序存储结构
如数组,顺序表
-
链式存储结构
如链表
-
索引存储结构
如键值对(主要在C++中)
A <–>B
-
散列结构
如:哈希表
好了,分类已经介绍完毕了。下面来介绍其中之一顺序表。
-
-
1.顺序表
特点 : 基于一维数组的实现,使用顺序存储结构,即存储时使用的连续的存储空间。
优点:查询效率高,因为采用了顺序存储结构,所有元素的空间是连续的。
缺点:容量容易达到上限,在进行插入和删除时需要进行大量的数据移动;要求存储空间必须是连续的。
实现代码;
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <strings.h>
#define MAX_SZ 5
struct seqlist
{
int array[MAX_SZ];
int length; //顺序表实际存储元素的个数
};
void InitList(struct seqlist * head);
void PrintList(struct seqlist *head);
//数据结构四大步:增,删,改,查
bool InsertElement(struct seqlist *head,int pos,int x); //在pos位置插入元素
bool RemoveElement(struct seqlist *head,int x); //删除值为x的元素
bool ChangeElement(struct seqlist *head,int x,int y); //将值为x的元素,改为y
bool SearchElement(struct seqlist *head,int x); //查一下值为x的元素
int main(void)
{
struct seqlist head; //创建一个顺序表
InitList(&head);
//插入4个元素
InsertElement(&head,0,10);
InsertElement(&head,1,20);
InsertElement(&head,2,30);
InsertElement(&head,3,40);
//遍历顺序表,并打印顺序表中已经存储的元素
PrintList(&head);
//删除元素
RemoveElement(&head,30);
PrintList(&head);
//替换元素
InsertElement(&head,2,50);
PrintList(&head);
//查询元素,查询值为30的元素的相关信息
SearchElement(&head,30);
return 0;
}
//初始化顺序表
void InitList(struct seqlist *head)
{
bzero(head->array,MAX_SZ);
head->length = 0;
}
bool InsertElement(struct seqlist *head,int pos,int x) //在pos位置插入元素
{
int i; //长度不能超过MAX_SZ
if(head->length >= MAX_SZ)
{
printf("顺序表已满.\n");
return false;
}
if(pos < 0 || pos > head->length)
{
printf("pos 位置超过范围.\n");
}
//将pos后面的值全部向后移动一位
for(i = head->length;i > pos;i--)
{
head->array[i] = head->array[i-1]; //从最后一位开始往后移
}
head->array[pos] = x;
head->length++;
printf("插入 %d 元素成功.\n",x);
return true;
}
//删除元素值为x的元素
bool RemoveElement(struct seqlist *head,int x)
{
int i,j,count = 0,pos = 0;
//判断顺序表是否为空
if(head->length == 0)
{
printf("顺序表为空.\n");
return false;
}
//在查询顺序表中是否存在值为x的元素
for(i = 0;i < head->length;i++)
{
if(head->array[i] == x)
{
for(j = i;j < head->length-1;j++) //思考为什么是length - 1
{
head->array[j] = head->array[j + 1];
}
head->length--;
i--; //i后面的值全部向前移动一位后,其下标值都减少了1,i值减少1,是为了让此时位于i位置的元素能够参与下一轮比较,避免漏比较元素
count++; //记录已经删除了多少个元素
}
}
if(count == 0)
{
printf("没有找到这个元素.\n");
return false;
}
else
{
printf("共删除%d个值为 %d 的元素.\n",count,x);
}
return true;
}
void PrintList(struct seqlist *head)
{
int i;
for(i = 0; i < head->length;i++)
{
printf(" %d ",head->array[i]);
}
printf("\n");
}
bool ChangeElement(struct seqlist *head,int x,int y)
{
int i;
if(head->length == 0) //判断是否为空
{
printf("顺序表为空.\n");
return false;
}
for(i = 0;i < head->length;i++)
{
if(head->array[i] == x) //将全部值为x的值改为y
{
head->array[i] = y;
}
}
return true;
}
bool SearchElement(struct seqlist *head,int x)
{
int i;
int count = 0;
if(head->length == 0)
{
printf("顺序表为空.\n");
return false;
}
for(i = 0;i < head->length;i++)
{
if(head->array[i] == x)
{
count++;
printf("元素 %d 的位置为 %d .\n",x,i);
}
}
printf("顺序表中元素 %d 共 %d 个.\n",x,count);
return true;
}