数据结构:
1.衡量一个程序是否优秀:
1.时间复杂度:
数据量增长与程序运行时间的比例关系以函数描述称为时间渐进复杂度函数,简称时间复杂度
O(c) > O(logn) > O(n) > O(nlogn) > O(n^2) > O(n^3) > O(2^n)
2.空间复杂度:
数据量增长与程序所占用空间的比例关系称为空间复杂度
2.数据结构:
数据之间的关系
逻辑结构:
1. 线性结构
一对一 表
2. 非线性结构
一对多 树
多对多 图
存储结构:
1. 顺序存储结构
2. 链式存储结构
3. 离散存储
4. 索引存储
3.程序:
程序 = 数据结构 + 算法
4.数据结构:
顺序表
链式表
顺序栈
链式栈
顺序队列
链式队列
树
二叉树
常见的排序查找算法
安装内存泄露检测工具:
sudo apt-get install valgrind
检测方法:
valgrind --tool=memcheck --leak-check=full ./a.out
5.顺序表:
#include "seqlist.h"
#include <stdlib.h>
#include <stdio.h>
//创建顺序表
SeqList *CreateSeqList(int MaxLen)
{
SeqList *pTmpList = NULL;
//1.申请标签空间
pTmpList = malloc(sizeof(*pTmpList));
if (NULL == pTmpList)
{
return NULL;
}
//2.对标签中的所有成员赋值
pTmpList->cLen = 0;
pTmpList->tLen = MaxLen;
//3.申请存放数据的空间
pTmpList->pData = malloc(MaxLen * sizeof(DataType));
if (NULL == pTmpList->pData)
{
return NULL;
}
//4.返回标签首地址
return pTmpList;
}
//顺序表是否已满
int IsFullSeqList(SeqList *pTmpList)
{
return pTmpList->cLen == pTmpList->tLen ? 1 : 0;
}
//顺序表是否为空
int IsEmptySeqList(SeqList *pTmpList)
{
return pTmpList->cLen == 0 ? 1 : 0;
}
//获得顺序表中元素个数
int GetCountSeqList(SeqList *pTmpList)
{
return pTmpList->cLen;
}
//获得顺序表中元素的容量
int GetCapacitySeqList(SeqList *pTmpList)
{
return pTmpList->tLen;
}
//末尾添加
int AppendSeqList(SeqList *pTmpList, DataType TmpData) //插入数据 直接是数据
{
if (IsFullSeqList(pTmpList))
{
return -1;
}
pTmpList->pData[pTmpList->cLen] = TmpData; //当前指向的clen就是下次插入的位置
pTmpList->cLen++;
return 0;
}
//指定位置插入
//注意:
// 返回-1 表示顺序表已满
// 返回-2 表示插入数据的位置错误
int PosInsertSeqList(SeqList *pTmpList, int Pos, DataType TmpData)
{
int n = 0;
if (IsFullSeqList(pTmpList))
{
return -1;
}
//错误的插入位置
if (!(Pos >= 0 && Pos <= pTmpList->cLen))
{
return -2;
}
for (n = pTmpList->cLen; n > Pos; n--) //0开始,指定位置插入,将从后边开始所有元素值依次向下移动
{
pTmpList->pData[n] = pTmpList->pData[n-1];
}
pTmpList->pData[Pos] = TmpData;
pTmpList->cLen++;
return 0;
}
//元素遍历
//参数:
// pFun:对遍历到的每个数据的操作方法
// arg:对pFun函数的传参
//返回值:
// 成功返回0
// 失败返回-1
int ForeachSeqList(SeqList *pTmpList, int (*pFun)(void *Element, void *arg), void *arg)
{
int i = 0;
int ret = 0;
for (i = 0; i < pTmpList->cLen; i++)
{
ret = pFun(&pTmpList->pData[i], arg);
if (ret != 0)
{
return -1;
}
}
return 0;
}
//删除
int DeleteSeqList(SeqList *pTmpList, int Pos)
{
int i = 0;
int n = 0;
if (IsEmptySeqList(pTmpList))
{
return -1;
}
if (!(Pos >= 0 && Pos < pTmpList->cLen))
{
return -2;
}
for (n = Pos; n < pTmpList->cLen-1; n++)
{
pTmpList->pData[n] = pTmpList->pData[n+1];
}
pTmpList->cLen--;
return 0;
}
//清0
int ClearSeqList(SeqList *pTmpList)
{
pTmpList->cLen = 0;
return 0;
}
//销毁
int DestroySeqList(SeqList **ppTmpList)
{
free((*ppTmpList)->pData);
free((*ppTmpList));
*ppTmpList = NULL;
return 0;
}
#ifndef __SEQLIST_H__
#define __SEQLIST_H__
//存储数据类型
typedef int DataType;
//顺序表标签结构
typedef struct list
{
DataType *pData; //存放数据空间首地址
int tLen; //最大存放元素个数
int cLen; //当前元素个数
}SeqList;
extern SeqList *CreateSeqList(int MaxLen);
extern int IsEmptySeqList(SeqList *pTmpList);
extern int IsFullSeqList(SeqList *pTmpList);
extern int GetCountSeqList(SeqList *pTmpList);
extern int GetCapacitySeqList(SeqList *pTmpList);
extern int AppendSeqList(SeqList *pTmpList, DataType TmpData);
extern int PosInsertSeqList(SeqList *pTmpList, int Pos, DataType TmpData);
extern int ForeachSeqList(SeqList *pTmpList, int (*pFun)(void *Element, void *arg), void *arg);
extern int DeleteSeqList(SeqList *pTmpList, int Pos);
extern int ClearSeqList(SeqList *pTmpList);
extern int DestroySeqList(SeqList **ppTmpList);
#endif
#include "seqlist.h"
#include <stdio.h>
int ShowFun(void *pElement, void *arg)
{
int *pData = pElement;
printf("%d ", *pData);
return 0;
}
int UpdateFun(void *pElement, void *arg)
{
int *pData = pElement;
if (*pData == 4)
{
*pData = 40;
}
return 0;
}
int FindFun(void *pElement, void *arg)
{
int *pData = pElement;
if (*pData == 30)
{
return 1;
}
else
{
(*(int *)arg)++;
}
return 0;
}
int main(void)
{
SeqList *pseqlist = NULL;
int val = 0;
int n = 0;
pseqlist = CreateSeqList(10);
AppendSeqList(pseqlist, 1);
AppendSeqList(pseqlist, 2);
AppendSeqList(pseqlist, 3);
AppendSeqList(pseqlist, 4);
AppendSeqList(pseqlist, 5);
PosInsertSeqList(pseqlist, 0, 10);
PosInsertSeqList(pseqlist, 3, 30);
printf("===============================\n");
printf("顺序表当前元素个数:%d/%d\n", GetCountSeqList(pseqlist), GetCapacitySeqList(pseqlist));
printf("===============================\n");
printf("元素内容:\n");
ForeachSeqList(pseqlist, ShowFun, NULL);
printf("\n");
printf("===============================\n");
printf("修改元素:\n");
ForeachSeqList(pseqlist, UpdateFun, NULL);
printf("===============================\n");
printf("元素内容:\n");
ForeachSeqList(pseqlist, ShowFun, NULL);
printf("\n");
printf("===============================\n");
printf("查找元素:\n");
n = 0;
ForeachSeqList(pseqlist, FindFun, &n);
printf("n = %d\n", n);
printf("===============================\n");
printf("删除元素:\n");
n = 0;
ForeachSeqList(pseqlist, FindFun, &n);
DeleteSeqList(pseqlist, n);
DeleteSeqList(pseqlist, 0);
DeleteSeqList(pseqlist, GetCountSeqList(pseqlist)-1);
printf("===============================\n");
printf("元素内容:\n");
ForeachSeqList(pseqlist, ShowFun, NULL);
printf("\n");
printf("===============================\n");
ClearSeqList(pseqlist);
printf("元素内容:\n");
ForeachSeqList(pseqlist, ShowFun, NULL);
printf("\n");
printf("===============================\n");
DestroySeqList(&pseqlist);
printf("pseqlist = %p\n", pseqlist);
return 0;
}
6.链表:
1.空间可以不连续,访问元素不方便
2.链表需要更大的空间存放数据和节点地址
3.链表空间不连续,使得理论上长度是无限的
4.链表的插入和删除效率很高
链表的分类:
1.单向链表
2.双向链表
3.循环链表
4.内核链表