目录
1.什么是数据结构
数据结构是具有逻辑关系,应用某种存储结构,封装相应操作的数据元素的集合。数据结构包括逻辑结构、物理结构以及数据的运算和实现。
2.线性数据结构
2.1数组
2.2链表
#include<stdio.h>
#include<stdlib.h>
#define N 10
typedef struct node {
int data;
struct node * next;
}ElemNode,*ElemTree;//定义节点
ElemNode* CreatLink(int arr[],int n){
ElemNode *p, *head, *tail;
head=NULL;
for(int i=0;i<n;i++){
p=(ElemNode*)malloc(sizeof(ElemNode));
p->data=arr[i];
p->next=NULL;
if(head)head=tail=p;
else tail=tail->next=p;//尾插法:若头部非空则下一个插入p
}
return head;
}
void PrintLink(ElemSN * head){
ElemSN * p;
for(p=head;p;printf("%3d",p->data),p=p->next);//输出链表
}
int main(void){
int arr[N];
ElemSN * head;
printf("输入要插入的10个元素:");
for(int i=0;i<N;scanf("%d",&arr[i]),i++);//输入要生成的链表元素,然后i自增
head = CreatLink(arr,N);
PrintLink(head);
}
2.3栈
2.31存储结构
·顺序栈的数据结构:
#define MAXSIZE 50
typedef int ElemType;
/*两栈共享空间结构*/
typedef struct{
ElemType data[MAXSIZE];
int top;
}Stack;
·链栈的数据结构:
typedef struct StackNode{
ElemType data;
struct StackNode *next;
}StackNode, *LinkStackPrt;
/*构造链栈*/
typedef struct LinkStack{
LinkStackPrt top;
int count;
}LinkStack;
2.32应用
递归
2.4队列
2.41存储结构
·顺序队列的数据结构:
#define MAXSIZE 50
typedef int ElemType;
typedef struct{
ElemType data[MAXSIZE];
int front,rear;
}SqQueue;
·链队列的数据结构:
..
2.42循环队列
·解决了假溢出的问题
·当队首指针Q->front = MAXSIZE-1
后,再前进一个位置就自动到0,这可以利用除法取余运算(%)来实现。
3.树
3.1二叉树
·先序遍历:根左右
·中序遍历:左根右
·后序遍历:左右根
#include<stdio.h>
#include<stdlib.h>
//二叉树结点的结构
typedef struct BiTNode
{
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//二叉树的先序建立
void CreateBiTree(BiTree *T)
{
char ch;
scanf("%c",&ch);
*T=(BiTree)malloc(sizeof(BiTNode));
if(!*T)
exit(-1);
(*T)->data=ch;
CreateBiTree(&(*T)->lchild);
CreateBiTree(&(*T)->rchild);
}
//二叉树的先序遍历
void PreOrderTraverse(BiTree *T)//T指向的地址才是
{
if(T==NULL)
return;
printf("%3c",T->data);
PreOederTraverse(T->lchild);
PreOederTraverse(T->rchild);
}
int main(void){
int arr[N];
BiTree head;
printf("输入要插入的元素:");
CreateBiTree(head);
PreOrderTraverse(head);
}
3.2二叉查找树(二叉搜索树,二叉排序树)
左子树的值<根节点的值<右子树的值
3.3平衡二叉树(AVL树)
或是一颗空树,或具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1。
//判断该二叉树是否AVL树
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int key;
struct Node *lchild;
struct Node *rchild;
int height;
}TreeNode;
int height(struct TreeNode* root){
if(root==NULL)
return 0;
else return fmax(height(root->left),height(root->right))+1;
//返回左右子树最大深度加上根节点
}
bool isBalanced(struct TreeNode* root)
{
if(root==NULL)
return true;
else
return fabs(height(root->left)-height(root->right))<=1&&isBalanced(root->left)&&isBalanced(root->right);//fabs是求绝对值
3.3哈夫曼树
3.4B树
平衡多路查找树
4.图
4.1图的存储结构
邻接矩阵--包含一个存储所有顶点的数组成员
邻接表(有向图为十字链表,无向图为邻接多重表)
边集数组
4.2图的遍历
4.21广度优先遍历
4.22深度优先遍历
5.排序
5.1直接插入排序
元素与nums[i]比较若元素小则时nums[i]向后移动否则插入元素
5.2折半插入排序
用二分法进行插入排序
5.3希尔排序
先将待排序列进行gap预排序,使待排序列接近有序,再进行一次插入排序,此时插入排序的时间复杂度为O(N),
5.5冒泡排序
·相邻两个元素进行比较,若逆序则交换,每交换一次无序部分的最后一个将变为有序(即最大);
#include<stdio.h>
#include<stdlib.h>
#define N 10
void BubbleSort(int arr[],int n){
int i;int j;
int temp;
int flag=1;//判断本轮循环是否有元素交换
//注意下标溢出!!!
for(i=n;i>0&&flag==1;i--)/*大循环flag为0则或循环次数为N-1则停止
i是循环下标的end,因为i到n都是有序数组*/
for(j=0,flag=0;j<i-1;j++)
{
if(arr[j]>arr[j+1]){
flag=1;//有元素交换
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;//交换元素
}}//注意下标
}
int main(void){
int nums[N];
for(int i=0;i<N;i++)
scanf("%d",&nums[i]);
BubbleSort(nums,N);
for(int i=0;i<N;i++)
printf("%d ",nums[i]);
}
5.6快速排序
·思路:先将数组中第一个元素取出,从后面找到比该元素小的元素再从前找比该元素小的元素两两交换,直到前后下标相同,将该元素与第一个元素交换,然后再将该元素前后的子集进行递归。
·时间复杂度:一次遍历时间复杂度为n,递归层次深度为lgn~n(最好情况是每次key值都在中间,这样就一共lg2n次,最坏情况是每次key值都在第一个,这样层次最深一共n次),总共的时间复杂度为O(nlgn);
#include<stdio.h>
#include<stdlib.h>
#define N 10
void QuickSort(int* arr, int begin, int end)
{ //begin和end是本轮循环中固定的起点和终点
int left = begin,right = end;
int key = arr[begin];//选取第一个元素作为参照
while (left < right)
{
//先将后面更小的元素放前面key的位置
while (arr[right] >= key && left < right)
{
right--;
}
arr[left] = arr[right];
//找大
while (arr[left] <= key && left < right)
{
left++;
}
//大的放到右边的坑里
arr[right] = arr[left];
}
//因为轮次问题本次轮到执行arr[left]=arr[right]
arr[left] = key;
/*
key的相对位置已经分好,此后key的位置将固定,
本轮循环实现了key前面所有元素小于key的后面所有元素大于key
*/
if(begin<left)
QuickSort(arr, begin, left- 1);//注意下标:整个数组开始和结束还是begin和end
if(right<end) //以key(下标为left)为分界点
QuickSort(arr, left+ 1, end);
}
int main(void){
int nums[N];
for(int i=0;i<N;i++)
scanf("%d",&nums[i]);
QuickSort(nums, 0, N-1);
for(int i=0;i<N;i++)
printf("%d ",nums[i]);
}
5.7简单选择排序
每次选一个最小的元素和无序数组中第一个元素交换
5.8堆排序
·思路:从n/2的节点开始,将非叶子节点与其子节点比较,若根比孩子大/小则交换,再n-1递归执行
·时间复杂度:下沉调整的时间复杂度等同于堆的高度O(logn),构建二叉堆执行下沉调整次数是n/2,循环删除进行下沉调整次数是n-1,时间复杂度约为O(nlogn)
5.9归并排序
·思路:归并排序对序列的元素进行逐层折半分组,然后从最小分组开始比较排序,合并成一个大的分组,逐层进行,最终所有的元素都是有序的
时间复杂度:每次遍历的时间复杂度是O(n),递归次数为O(lgn),总共时间复杂度是O(nlgn)
5.10基数排序
5.9比较排序性能:
1.时间性能:
1)O(nlogn):快速排序、堆排序、归并排序
2)O(n^2):直接插入排序、冒泡排序、简单选择排序
3)O(n):基数排序
2.空间性能: