一.数据结构基本概念
1.1基本概念
数据:是客观事物的符号表示,指的是能够被输入到计算机中并且能够被计算机识别和处理的符号的总称。
数据元素:是数据的基本单位。
数据项:是组成数据元素的最小单位,不可分割。
数据对象:是性质相同数据元素的集合
数据结构:是相互之间存在一种或多种对应关系的集合。
1.2数据结构的三要素
数据结构的三要素为:逻辑结构,存储结构,运算。
1.2.1逻辑结构
逻辑结构分为:线性结构与非线性结构
线性结构:数据元素之间存在一对一的关系。例如:线性表,栈,队列
非线性结构:数据元素之间存在多对多的关系或者一对多的关系。例如:树,图
1.2.2存储结构
存储结构分为:顺序存储,链式存储,散列存储
1.顺序存储:是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,使用顺序存储的存储的数据
在内存中占用一片连续的内存空间。
2.链式存储:不要求存储的元素占用一片连续的内存空间,但是要求每个元素都有附加指针字段,用千存放后继元素的存储地址
1.3算法的五个特性
1.有穷性:算法必须在执行有穷步骤后结束。
2.确定性:执行的操作不应该有歧义
3.可行性:操作都可以执行
4.输入:一个算法有零个或多个输入
5.输出:个算法有一个或多个输出
1.4算法的基本标准
1.正确性。在合理的数据输入下,能够在有限的运行时间内得到正确的结果。
2.可读性。一个好的算法,应便千人们理解和相互交流.
3.健壮性。当输入的数据非法时,好的算法能适当地做出正确反应或进行相应处理,而不
会产生一些莫名其妙的输出结果。
4.高效性。高效性包括时间和空间两个方面。一般是空间换取时间。
二.顺序表
2.1顺序表的结构
顺序表的结:
1.逻辑结构:顺序表是线性的
2.存储结构:顺序表使用的是顺序存储
优点:随机查找元素效率高,可以直接使用下标来操作
缺点:任意位置添加元素和删除元素比较麻烦,因为需要批量移动元素
2.2顺序表的实现(C语言实现)
2.2.1顺序表的创建
创建一个顺序表:
表中包含一个结构体数组,一个计数器
声明文件:seq_list.h
#ifndef __SEQ_LIST_H__
#define __SEQ_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 50 //顺序表的最大长度
typedef struct DATA{
int num;
}data_t;
typedef struct SEQLIST{
data_t elem[MAXSIZE];//创建一个struct DATA类型的数组
int count; //数组里面元素的个数
}sql_list; //顺序存储结构为sq_list
int InitList(sql_list ** sqlist);//初始化顺序表
#endif
初始化表的定义:seq_list.c
int InitList(sql_list ** sqlist){
if (NULL==*sqlist) //判断传入指针的指向
{
*sqlist=(sql_list*)malloc(sizeof(sql_list));//开始在堆区分配内存空间
}
if(NULL==*sqlist){ //判断是否分配失败
printf("堆区分配空间失败");
return-1;
}
printf("分配空间成功:%p\n",*sqlist);//测试
return 0;
}
函数调用:main.c
#include "seq_list.h"
int main(){
sql_list * sqlist=NULL;//初始化指针,防止野指针
InitList(&sqlist);
/*
InitList(sqlist);//值传递
函数声明为:
int InitList(sql_list * sqlist);这种初始化方式错误,因为对指针的更改仅在函数内部生效,
不会影响到函数外部,因为出了初始化函数,里面的指针就被销毁了
*/
return 0;
}
2.2.2顺序表的增删改查与去重
1.声明文件:seq_list.h
#ifndef __SEQ_LIST_H__
#define __SEQ_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 5 //顺序表的最大长度
typedef struct DATA{
int num;
}data_t;
typedef struct SEQLIST{
data_t elem[MAXSIZE];//创建一个struct DATA类型的数组
int count; //数组里面元素的个数
}sql_list; //顺序存储结构为sq_list
int InitList(sql_list ** sqlist);//初始化顺序表
int Insert_seq_list_tail(sql_list *sqlist, int ele);
/*这个可以使用一级指针,因在这里面定义的sqlist指向的也是
堆区分配的内存空间,即可以在这里操作堆区的内容*/
int Insert_seq_list_pos(sql_list *sqlist,int pos,int ele);//任意位置插入
int delete_seq_list_pos(sql_list *sqlist,int pos);//随意位置删除,根据元素所在位置删除。
int delete_seq_list_tail(sql_list *sqlist);//尾删除
int modify_seq_list_pso(sql_list *sqlist,int pos,int ele);//根据位置该元素
int serach_seq_list_pso_data(sql_list *sqlist,int pos);//根据位置查元素
int clean_seq_list(sql_list *sqlist);//清空线性表
int destory_seq_list(sql_list **sqlist);//线性表的销毁
int nodup_seq_list(sql_list *sqlist);//去除重复元素
int printf_sqlist(sql_list *sqlist);
//作用:1.测试代码是否错误
//2.遍历元素
#endif
2.函数定义:seq_list.c
#include "seq_list.h"
int InitList(sql_list ** sqlist){
if (NULL==*sqlist)
{
*sqlist=(sql_list*)malloc(sizeof(sql_list));
}
if(NULL==*sqlist){
printf("堆区分配空间失败");
return-1;
}
printf("分配空间成功:%p\n",*sqlist);
return 0;
}
//尾插法
int Insert_seq_list_tail(sql_list *sqlist,int ele){
/*如果一个指针变量未初始化或者没有被明确地分配内存,它的值通常
会是NULL。因此,在对指针进行操作之前,我们需要先检查指针是否为NULL,
以避免在访问无效的内存地址时出现错误。*/
if(NULL==sqlist){
printf("传入参数为NULL\n");
return -1;
}
if (sqlist->count==MAXSIZE){
printf("元素已满,元素插入失败\n");
return -1;
}
sqlist->elem[sqlist->count].num=ele;
sqlist->count++;
return 0;
}
//任意位置插入
int Insert_seq_list_pos(sql_list *sqlist,int pos,int ele){
//判断插入元素是否合法
if(NULL==sqlist){
printf("传入参数为NULL\n");
return -1;
}
if (sqlist->count==MAXSIZE){
printf("元素已满,元素插入失败\n");
return -1;
}
if (pos<0||pos>sqlist->count)
{
printf("插入位置不合法\n");
return -1;
}
for(int i=sqlist->count;i>pos;i--){//注意越界问题
sqlist->elem[i]=sqlist->elem[i-1];
}
sqlist->elem[pos].num=ele;
sqlist->count++;
printf("插入成功\n");
return 0;
}
//尾删除
int delete_seq_list_tail(sql_list *sqlist){
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
if (sqlist->count==0)
{
printf("表中已无元素,删除失败\n");
return -1;
}
sqlist->count--;
return 0;
}
//随意位置删除
int delete_seq_list_pos(sql_list *sqlist,int pos){
//判断传入参数
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
}
//判断表中的元素是否为空
if (sqlist->count==0)
{
printf("表中已无元素,删除失败\n");
return -1;
}
//判断删除位置是否合法
if (pos<0||pos>sqlist->count)
{
printf("删除位置不合法\n");
return-1;
}
for(int i=pos;i<sqlist->count-1;i++){//注意越界
sqlist->elem[i]=sqlist->elem[i+1];
}
printf("删除完成\n");
sqlist->count--;
return 0;
}
//修改元素的值,根据下标进行修改
int modify_seq_list_pso(sql_list *sqlist,int pos,int ele){
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
//判断表中的元素是否为空
if (sqlist->count==0)
{
printf("表中已无元素,修改失败\n");
return -1;
}
//判断修改位置是否合法
if (pos<0||pos>sqlist->count)
{
printf("修改位置不合法\n");
return-1;
}
sqlist->elem[pos].num=ele;
return 0;
}
//根据位置查元素
int serach_seq_list_pso_data(sql_list *sqlist,int pos){
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
//查看表是否为空
if (sqlist->count==0)
{
printf("表中无元素,无需查找\n");
return -1;
}
return sqlist->elem[pos].num;
}
//清空顺序表
int clean_seq_list(sql_list *sqlist){
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
//查看表是否为空
if (sqlist->count==0)
{
printf("表中无元素,无需清空\n");
return -1;
}
sqlist->count=0;
return 0;
}
//销毁顺序表
int destory_seq_list(sql_list **sqlist){
if (NULL==sqlist||NULL==*sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
free(*sqlist);//释放空间
*sqlist=NULL;//空间被释放后,就不属于这一段程序了,即需要将指针指向置NULL
return 0;
}
//去重
int nodup_seq_list(sql_list *sqlist){
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
//查看表是否为空
if (sqlist->count==0)
{
printf("表中无元素,无需去重\n");
return -1;
}
for(int i=0;i<sqlist->count;i++){
for(int j=i+1;j<sqlist->count;){
//去重
if(sqlist->elem[i].num==sqlist->elem[j].num){
//注意越界问题
for (int k = j; k < sqlist->count-1; k++)
{
sqlist->elem[k]=sqlist->elem[k+1];
}
//去重完成后,元素个数减1,但是内层循环下标j不变
sqlist->count--;
// delete_seq_list_pos(sqlist,j);
continue;
}
j++;
}
}
return 0;
}
//打印
int printf_sqlist(sql_list *sqlist){
//检查传入参数是否错误
if (NULL==sqlist)
{
printf("传入参数为NULL\n");
return -1;
}
for (int i = 0; i < sqlist->count; i++)
{
printf("%d ",sqlist->elem[i].num);
}
printf("\n打印完成\n");
return 0;
}
3.函数调用:main.c
#include "seq_list.h"
int main(){
sql_list * sqlist=NULL;//初始化指针,防止野指针
InitList(&sqlist);
/*
InitList(sqlist);//值传递
函数声明为:
int InitList(sql_list * sqlist);这种方法传递的是
值传递,这种初始化方式错误,因为出了初始化函数,里面的
指针就被销毁了
*/
Insert_seq_list_tail(sqlist,8);
Insert_seq_list_tail(sqlist,8);
Insert_seq_list_pos(sqlist,0,8);
Insert_seq_list_tail(sqlist,8);
Insert_seq_list_tail(sqlist,8);
delete_seq_list_tail(sqlist);
Insert_seq_list_tail(sqlist,8);
modify_seq_list_pso(sqlist,0,8);
delete_seq_list_pos(sqlist,2);
printf_sqlist(sqlist);
printf("%d的元素查找成功\n",serach_seq_list_pso_data(sqlist,0));
nodup_seq_list(sqlist);
printf_sqlist(sqlist);
return 0;
}