数据结构概述

数据结构概述


1、定义:

我们如何把现实中大量而复杂的问题以特定的数据类型特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(比如查找某个元素,删除某个元素,对所有元素进行排序而执行的相应操作,这个相应的操作也叫算法)。

个体如何保存,个体与个体之间的关系如何保存。

2、算法:

数据结构解决存储的问题,算法解决操作的问题。

解题的方法和步骤

衡量算法的标准:

  • 时间复杂度:大概程序要执行的次数,而非执行的时间
  • 空间复杂度:算法执行过程中大概所占用的最大内存
  • 难易程度
  • 健壮性

3、数据结构的地位

数据结构是软件中最核心的课程

程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言


一、预备知识

1、指针

指针的重要性:

指针是C语言的灵魂

定义:

地址:内存单元的编号。

指针:指针占四个字节

    double *q;
    double x = 66.6;
    q = &x; //x占8个字节,1个字节是8位,1个字节一个地址

    double arr[] = {1.1,2.2,3.3};
    q = &arr[0];
    printf("%p\n",q);   //%p实际就是以十六进制输出
    q = &arr[1];        //指针变量统一只占四个字节
    printf("%p\n",q);   //[0]与[1]差八个字节
  • 指针就是地址,地址就是指针。
  • 指针变量是存放内存单元地址的变量。
  • 指针的本质是一个操作受限的非负整数。

2、结构体

  • 为什么会出现结构体:

为了表示一些复杂的数据

struct Student
{
    int sid;
    char name[200];
    int age;
};

struct Student st = {100,"zhangsan",20};
printf("%d, %s, %d\n",st.sid,st.name,st.age);

st.sid = 99;
//st.name = "list";
strcpy(st.name,"list");
st.age = 11;
printf("%d, %s, %d\n",st.sid,st.name,st.age);
  • 什么叫结构体:

结构体是用户根据实际需要自己定义的复合数据类型。

  • 如何使用结构体:
#include <string.h>

struct Student
{
    int sid;
    char name[200];
    int age;
};

struct Student *pst = &st;
pst->age = 10;
strcpy(pst->name,"li");
pst->sid = 11;
printf("%d, %s, %d\n",pst->sid,pst->name,pst->age);
  • 注意事项:

结构体变量不能加减乘除,但可以相互赋值。

普通结构体变量和结构体指针变量作为函数传参的问题:传结构体变量耗内存,耗时间。


3、动态内存的分配和释放

#include<malloc.h>

int a[5] = {3,1,4,8,7};
int len;
printf("请输入你需要分配的数组的长度:len = ");
scanf("%d",&len);
int *pArr = (int*)malloc(sizeof(int)*len);
for(int i =0 ;i<len;i++)
{
    scanf("%d",&pArr[i]);
}
for(int i =0;i<len;i++)
{
    printf("%d\n",*(pArr+i));
}
//*pArr = 4;
//pArr[1] = 10;
//printf("%d, %d\n",*pArr,pArr[1]);

free(pArr);

二、模块一:线性结构【把所有的节点用一根直线穿起来】

1、连续存储【数组】:

  1. 什么叫数组:元素类型相同,大小相等
  2. 数组的优缺点:

代码如下:

#include <iostream>
#include <stdio.h>
#include <malloc.h>

using namespace std;

//定义了一个数据类型,该数据类型的名字叫做struct Arr,该数据类型含有三个成员
//分别是pBase,len,cnt;
struct Arr
{
  int *pBase;   //存储的是数组的第一个元素的地址
  int len;      //数组所能容纳的最大元素的个数
  int cnt;      //当前数组有效元素的个数
};

void init_arr(struct Arr * pArray);
bool append_arr(struct Arr &Array, int value);  //追加
bool insert_arr(struct Arr &Array, const int pos, int val);
bool delete_arr(struct Arr &Array, const int pos, int &val);
int get(struct Arr &Array, const int &pos);
bool is_empty(const struct Arr &Array);
bool is_full(const struct Arr &Array);
void sort_arr(struct Arr &Array);
void show_arr(const struct Arr &Array);
void inversion_arr(const struct Arr &Array);

void init_arr(struct Arr * pArray)
{
    int len = 0;
    printf("please input the size of array: ");
    scanf("%d",&len);
    int *pBase = (int*)malloc(sizeof(int)*len);
    pArray->pBase = pBase;
    pArray->len = len;
    pArray->cnt = 0;
}

void show_arr(const struct Arr &Array)
{
    if (is_empty(Array))
        printf("array is empty!");
    else
    {
        for(int i = 0;i<Array.cnt;i++)
        {
            printf("%d ",Array.pBase[i]);
        }
    }
    printf("\n");
}

bool is_empty(const struct Arr & Array)
{
    if ( 0 == Array.cnt)
        return true;
    else
        return false;
}

bool is_full(const struct Arr &Array)
{
    if (Array.cnt == Array.len)
        return true;
    else
        return false;
}

bool append_arr(struct Arr &Array, int value)
{
    if (is_full(Array))
        return false;
    else
    {
        Array.pBase[Array.cnt] = value;
        (Array.cnt)++;
    }
}

bool insert_arr(struct Arr &Array, const int pos, int val)
{
    if (is_full(Array))
        return false;
    else if (pos<1 || pos > Array.cnt+1)
        return false;
    else
    {
        for(int i = Array.cnt-1;i>= pos-1;i--)
        {
            Array.pBase[i+1] = Array.pBase[i];
        }
        Array.pBase[pos-1] = val;
        Array.cnt++;
        return true;
    }
}

bool delete_arr(struct Arr &Array, const int pos, int &val)
{
    if (is_empty(Array))
        return false;
    if (pos<1 || pos>Array.cnt)
        return false;
    else
    {
        val = Array.pBase[pos-1];
        for(int i = pos; i<Array.cnt;i++)
        {
            Array.pBase[i-1] = Array.pBase[i];
        }
        Array.cnt--;
    }
}

int get(struct Arr &Array, const int &pos)
{
    if (pos <1 || pos>Array.cnt)
        return -1;
    return Array.pBase[pos-1];
}

void inversion_arr(const struct Arr &Array)
{
    int i =0;
    int j = Array.cnt-1;
    int temp;
    while(i<j)
    {
        temp = Array.pBase[j];
        Array.pBase[j] = Array.pBase[i];
        Array.pBase[i] = temp;
        i++;
        j--;
    }
}

void sort_arr(struct Arr &Array)
{
    int temp = 0;
    for(int i =0;i<Array.cnt-1;i++)
    {
        for(int j = i+1;j<Array.cnt;j++)
        {
            if(Array.pBase[i]> Array.pBase[j])
            {
                temp = Array.pBase[i];
                Array.pBase[i] = Array.pBase[j];
                Array.pBase[j] = temp;
            }
        }
    }
}

int main()
{
    struct Arr stArray;
    init_arr(&stArray);
    show_arr(stArray);

    append_arr(stArray, 2);
    append_arr(stArray, 3);
    append_arr(stArray, 6);
    append_arr(stArray, 1);
    show_arr(stArray);

    insert_arr(stArray, 2,89);
    show_arr(stArray);
    insert_arr(stArray, 9, 2);
    show_arr(stArray);

    int val = 0;
    delete_arr(stArray, 2, val);
    printf("删除的是%d\n",val);
    show_arr(stArray);

    printf("%d\n",get(stArray, 9));

    inversion_arr(stArray);
    show_arr(stArray);

    sort_arr(stArray);
    show_arr(stArray);
    return 0;
}

 2、离散存储【链表】:

1.定义: n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一个后续节点,首节点没有前驱节点,尾节点没有后续节点。

专业术语:

首节点:第一个有效节点。

尾节点:最后一个有效节点。

头结点:第一个有效节点之前的那个节点,头结点并不存放有效数据,加头结点的目的主要是为了方便对链表的操作。

头指针:指向头结点的指针变量。

尾指针:指向尾节点的指针变量。

 

确定一个链表需要几个参数:

 

2. 分类:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值