数据结构
数据结构:
1、逻辑结构:描述数据与数据之间的关系
a、集合结构:
数据与数据之间除了属于同一集合,再无其他关系
b、线性结构:
数据与数据之间呈现一对一关系,线性关系(元素前只有一个元素,元素后也只有一个元素)
c、树型结构:
数据与数据之间呈现一对多的关系,树型关系(层次关系,从属关系,元素前只有一个元素,元素后可以有多个元素)
d、图型结构:
数据与数据之间呈现多对多的关系,(数据与数据之间都可能存在关系,元素前可以有多个元素,元素后可以有多个元素)
2、存储结构:描述数据的存储,同时存储关系
a、顺序存储
b、链式存储(离散存储)
3、数据运算:
运算:
对存在关系的数据能够进行处理
增、删、改、查
线性表
1.顺序表
例题:
#include<stdio.h>
#include<stdlib.h>
struct seqlist
{
int data[20];
int num;
int size;
};
struct seqlist * seqlist_create()
{
struct seqlist *p=malloc(sizeof(struct seqlist));
p->num=0;
p->size=20;
return p;
}
void seqlist_insert(struct seqlist *seq,int pos,int datasum)
{
if(seq->num<pos)
{
printf("位置错误\n");
return;
}
if(seq->size==seq->num)
{
printf("已存满\n");
return ;
}
for(int i=seq->num-1;i>=pos;i--)
{
seq->data[i+1]=seq->data[i];
}
seq->data[pos]=datasum;
seq->num++;
}
void seqlist_delete(struct seqlist *seq,int pos)
{
if(pos>seq->num)
{
printf("位置错误\n");
return ;
}
if(seq->num==0)
{
printf("顺序表为空\n");
return ;
}
for(int i=pos;i<seq->num-1;i++)
{
seq->data[i]=seq->data[i+1];
}
seq->num--;
}
void seqlist_search(struct seqlist *seq,int cha)
{
for(int i=0;i<seq->num;i++)
{
if(seq->data[i]==cha)
{
printf("%d在第%d位\n",cha,i);
}
}
}
void seqlist_show(struct seqlist *seq)
{
for(int i=0;i<seq->num;i++)
{
printf("%d ",seq->data[i]);
}
printf("\n");
}
int main()
{
struct seqlist *seq=seqlist_create();
seqlist_insert(seq,0,10);
seqlist_insert(seq,2,20);
seqlist_insert(seq,1,30);
seqlist_insert(seq,2,50);
seqlist_show(seq);
seqlist_delete(seq,1);
seqlist_show(seq);
seqlist_search(seq,50);
return 0;
}
2.链表
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node * linklist_create()
{
struct Node *p=malloc(sizeof(struct Node));
p->next=NULL;
return p;
}
void linklist_insert(struct Node *head,int pos,int data)
{
struct Node* p=head;
int i=0;
while(p->next!=NULL)
{
if(i==pos-1)
break;
i++;
p=p->next;
}
struct Node *q=malloc(sizeof(struct Node));
q->next=p->next;
p->next=q;
q->data=data;
}
void linklist_delete(struct Node* head,int pos)
{
if(head->next==NULL)
{
printf("链表为空\n");
return;
}
struct Node* p=head;
int i=0;
while(i!=pos-1&&p->next!=NULL)
{
p=p->next;
i++;
}
struct Node* q=p->next;
p->next=q->next;
printf("删除的值为%d\n",q->data);
free(q);
}
void linklist_show(struct Node* head)
{
struct Node *p=head;
while(p->next!=NULL)
{
p=p->next;
printf("%d ",p->data);
}
printf("\n");
}
int main()
{
struct Node *head=linklist_create();
linklist_delete(head,5);
linklist_delete(head,1);
linklist_insert(head,5,10);
linklist_insert(head,1,20);
linklist_insert(head,2,30);
linklist_insert(head,5,40);
linklist_insert(head,5,50);
linklist_insert(head,5,60);
linklist_show(head);
linklist_delete(head,4);
linklist_delete(head,1);
linklist_show(head);
return 0;
}
循环链表
单链表的首位相连,即单链表中的最后一个结点的next指针域存储单链表的头结点地址
作用:
可以从任意一个结点位置遍历单链表的所有结点
如何创建循环单链表:
创建头结点时,next指针存储头结点地址
struct Node *head = malloc(sizeof(struct Node));
//head是头指针
head->next = head;
如何判断单链表结束:
当前结点地址为p:,头结点地址为head
p->next == head;表示p就是最后一个结点
双向链表
栈
1.顺序栈
单独设置一个整型变量表示连续空间的下标top,来表示栈顶指针
例题:
2.链式栈
把头结点的next作为栈顶指针
例题:
队列
在一端进行插入,一端进行删除的线性表,就叫做队列
1.顺序队列(循环队列)
例题:
2.链式队列
例题:
树
树型关系:
是指数据与数据之间呈现一对多的关系(层次结构)
树的概念
结点的度:是指结点拥有子树的个数(拥有分支的数目)
树的度:指树中结点的度 的最大值称为树的度
叶子结点(终端结点):指度为0的结点,称为 叶子结
孩子结点(子结点):是指结点的子树的根节点,称为该结点的孩子
双亲结点(父结点):指结点的根结点称为该孩子结点的双亲
兄弟结点:是指同一个双亲的孩子,称为兄弟
树的深度(高度):树中结点的最大层次(层数)称为树的深度
有序数和无序树
如果把树中结点的子树,看做是从左往右有次序的(即不能交换),则称该树为有序树
森林:多棵互不相交的树的集合
二叉树
1、在二叉树中第k层上最多有 2^(k-1)个结点
2、在深度为k的二叉树中,最多有2^k - 1结点
3、对于任意二叉树,如果叶子结点树为 n0,度为2的结点数为 n2,
存在:n0 = n2+1
满二叉树:
一颗深度为k且有 2^k - 1个结点的二叉树称为满二叉树
完全二叉树:
深度为k,在k-1层之前是满二叉树,最后一层,从左往右叶子结点都是相邻
顺序存储
链式存储
先序遍历:根---左---右
中序遍历:左---根---右
后序遍历:左---右---根
层次遍历:层次遍历从第一层开始,依次访问每一层的所有结点
哈夫曼树
权值:二叉树中的结点存放了权重值
路径长度:从根节点到当前结点所经过的分支数目
带权路径长度:路径长度 * 权值
树的带权路径长度:是指 在二叉树所有叶子结点的带权路径长度之和
哈夫曼树:带权路径长度最小的二叉树,就叫做哈夫曼树
图
图:有两个集合,一个用于存储图中的元素叫做顶点集合,另一个用于存储图中的元素关系叫做边集合
无向边:顶点之间的关系是相互的
有向边:顶点之间的关系是单向的,也叫做弧
有向图:含有有向边的图
无向图:含有无向边的图
稠密图:在图中顶点的关系比较多
稀疏图:在图中顶点的关系比较少
路径:两个顶点之间,存在一条可以到达的关系
连通图:任意两个顶点之间都存在路径
连通分量:在图中,部分顶点之间是连通的就叫做图的连通分量
极大连通子图:在连通子图外,额外添加任意图中一个点,不能构成连通,则是极大连通子图
网:带权图,每条边上都有权值
图的存储:邻接矩阵或者邻接表
算法
折半查找
设置端点查找范围
mid = (low + high) / 2
mid就是当前中间位置
比较待查找数据与中间值:
相等:则查找成功
x < mid:x只会落在mid的左边 high = mid-1
x > mid:x只会落在mid的右边 low = mid +1
没查找到数据的结束条件:
low > high
直接选择排序(选择排序)
从数据中,找到最小的数据,直接与排序位置进行交换,直接选择最小的数据,进行交换
冒泡排序(交换排序)
在整个数据元素中,把相邻的两个元素进行比较,把较大的元素放在后面,依次进行相邻两个元素比较,当比较完后得到最大的数放在最后