数据结构
- 基础知识
概念:数据组织的不同方式 以及 运算步骤 提高效率和空间利用情况
复杂度:运算次数
常用算法的复杂度分析:等学了算法来分析
逻辑结构(抽象数据类型 比如线性表 树 图)和储存结构 - 表ADT
顺序储存:数组,在存储空间上 连续整块的空间 需要判别满不满
链式储存:数据分散在物理空间中 然后通过一条线保存逻辑关系 需要判别空不空
线性表:就是一对一的数据关系。是数据结构中的逻辑结构
//线性表的定义:具有相同特性数据元素的有限序列(1:1的)
typedef struct LNode *List;// *List 是新类型struct Lnode的别名,指针类型的
struct LNode{ // 新类型中的元素
ElementType Data[MAXSIZE];
int Last;// 长度-1
}; //上一步定义结构体
// 后面两个利用结构体定义两个变量
Struct LNode L;//定义结构体类型变量
List PtrL;//定义结构体指针变量
A:数组实现线性表的: 顺序表 初始化
// 数组的初始化
List Make Empty(){// 初始化的结构
List PtrL;
PtrL = (List)malloc(sizeof(struct LNode));
PtrL -> Last = -1;// -> 在c中用于只想结构体子数据的指针没有元素
return PtrL;// PtrL 是这个结构体的别名
}
//顺序表的查找
int Find(element type X,List PtrL){
int i =0;
while (i <= PtrL->Last && Ptrl->Data[i]!=X)
i++;// 没有到最后一个 并且元素没匹配就是 +1找下一个
if(i>PTrl->Last) return -1; //这种情况就是没有找到
else return i;
}
//顺序表的插入 第i个位置
// 1:移动 从后面开始挪
void insert(element type x,int i, List PtrL){
int j;
if(PtrL -> Last == MAXSIZE-1){
printf("表满");
return;}
if(i<1 || i > PtrL -> Last +2){ // 因为线性表连续的定义 而且last是从0开始数的
printf("位置不合法");
return;}
// 通过一个for循环把 i-1后面的往后面移
for(j = PtrL -> Last;J>= i-1;j--) // 数组从0开始 所以第i个位置插入 得从i-1开始挪
PtrL -> Data[j+1] = PtrL->Data[j];
PtrL ->Data[i-1] = X;
Ptrl -> Last++
return;
}
//顺序表的删除操作
void delete(int i ,List PtrL){
If(PtrL -> Last == -1){
printf("表空");
return;
}
if(i < 1 || i > PtrL -> Last + 1){
printf("位置不合法");
return;
}
for(j = i;j > PtrL->Last;j++){// for 循环的时候 等于 也要考虑进去
PtrL -> Data[j-1] = PtrL -> Data[j];
}
PtrL -> Last--;
}
链表:通过指针实现的不连续储存 不要求物理空间相邻
常用的操作:数据对象的长度测量,元素的增加/删减,找特定位置的元素
//定义
typedef Struct Lnode *List;
struct Lnode{//每个节点都是一个结构
ElementType Data;//
List Next;// 这里的话就是一个区域一个结构体是吗 因为内存结构是分散的
};
struct Lnode L;
List PtrL;
int Length(List PtrL){
List p = PtrL;//第一个的指针到最后一个指针 直到指到null;临时指针list 结构体类型的指针
int J = 0;
while(p){
p = p->Next;
j++
}
return j;
}//O(n)
// 查找
List FindKth(int K, List PtrL){
List p = PtrL;
int i = 1;
while(!p = NULL && i <k){
p = p->NEXT;//必须要一个一个遍历到
i++;//退出循环有两种可能。一种不够长 一种找到了
}
if(i == K)
return p;
else return NULL;
}
//按值查找
List Find(element type X, List PtrL){
List p = PtrL;//临时指针;
while(p-> Data != X && p!=NULL)
p=p->Next;//遍历的体现
return p
}
// 插入
List insert(element type X,int i, List PtrL){
// 只要修改两个指针的情况
list p ,s;
if(i == 1){
s = (List)malloc(sizeof(struct LNode));//分配一块新的内存空间。
s -> Data = X;//赋值
s -> Next = PtrL;//直接指向一开始的
return s;
}
p = FindKth(i-1,PtrL);//找到第i-1个的指针
if(p == NULL){
printf("参数错");
return NULL;
}else{
s = (List)malloc(sizeof(struct LNode));
s->Data = X;
s->Next = P->Next;//原来的指向给到现在新的
p->Next = s;//重新指 这两部有顺序要求
return Ptrl;
}
}
// 删除
List delete(int i, List PtrL){
//
list s,p
if(i == 1){
s = PtrL;
if(PtrL != NULL)
PtrL = PtrL -> Next;
else return NULL;
free(s);
return PtrL
}
p = FindKth(i-1,PtrL);//找到第i-1个的指针 找到前一个节点
if(p == NULL){
printf("参数错");
return NULL;
}else if(p->Next == NULL){
printf("这个指向的节点不存在");//最后一个节点是删不了的
}else{
s = P->Next;
p->Next = S->Next;
free(s);
return Ptrl;
}
}
- 栈ADT
堆栈是什么:逻辑结构还是存储结构
栈的应用情况:后缀表达式,从左到右然后逐个运算 所以对于这种运算,顺序储存运算数 然后倒序输出 。
定义: 具有一定约束的线性表,只在顶端进行插入 删除。
插入数据:入栈 删除数据 出栈 后入先出的规则
//数组实现
//一个一维数组 加一个记录栈顶元素位置的变量
#define MAXSIZE
typedef struct SNode *Stack;
struct SNode{
ElementType Data[MaxSize];
int Top;// 数组下表 栈顶的
}
//入栈
void push(Stack PtrS,ElementType item){
if(PtrS->Top == MAXSIZE -1 ){
printf("堆栈满");return;
}else{
PtrS->Data[++(PtrS->Top)] = item;
}
}
//出栈
//return 一个值 top减一
void pop(Stack PtrS){
if(PtrS->Top == -1 ){
printf("堆栈空");return ERROR;
}else{
return(PtrS->Data[(PtrS->Top)--]));// 直接修改了数组的size;
//栈顶少一
};
}
// 一个数组实现两个堆栈
#define MAXSIZE;
structure Dstack{
Elementype Data[MaxSize];
int Top1;//。栈顶指针
int Top2;// 栈顶指针
}
S.top1=-1;//起始值
S.top2 = MaxSize;//起始值
//push
void Push(struct DStack *PtrS,Element type item,int Tag){
if(Ptrs->Top2 - PtrS->Top1 ==1){
printf("堆栈满");return;
if(Tag == 1)
PtrS->Data[++(PtrS->Top1)] = item;
else
PtrS->Data[--(PtrS->Top2)] = item;
}
}
// 出栈
void pop(stuct DStack *PtrS,int Tag){
if(Tag == 1){
if(PtrS->Top1 == -1){
printf("堆栈1空");return NULL;
}
else{
return Ptrs->Data[(PtrS->Top1)--];
}
}
else{
if(PtrS->Top2 == MaxSize){
printf("堆栈2空");return NULL;
}
else{
return Ptrs->Data[(PtrS->Top1)++];
}
}
}
}
利用链表实现栈:
单链表 插入和删除只能在栈顶进行。
所以用单向链表的头 做栈顶(删除和插入都比较方便)链尾不行
// 定义
typedef struct Snode *Stack;
struct Snode{
ElementType Data;
struct Snode *Next;//这种类型的指针
}
//建立一个栈
Stack CreatStack(){
Stack S;
S = (Stack)Malloc(sizeof(struct SNode));
s->Next = NUll;
return S;
}
// 判断堆栈是否是空
int Isempty(Stack S){
return (S->Next == NULL);
}
//push
Void Push(ElementType item, Stack S){
struct Snode *tepcell ;// 定义一个临时的
Tepcell = (Struct Snode *)Malloc(sizeof(struct Snode));//给临时指针分配空间
Tepcell -> Element = item;
Tepcell -> Next = S->Next;//指向的变换
S->Tepcell = Tepcell;//更改头指针
}
// pop
ElementType Pop(Stack S){
struct Snode *Firstcell ;// 定义一个临时的
ElementType TopElem;
if(Isempty(S)){
printf("栈空");return NULL;
}
else{
FirstCell = S->Next;
S->Next = FirstCell ->Next;
TopElem = FirstCell->Element;
free(FirstCell);//释放空间
return TopElem;
}
}
堆栈的用途:实现函数调用以及递归的实现
5. 队列ADT
受限制的线性表 先进先出表 queue
入队:一端
出队:另一端
//顺序存储定义
#define MaxSize
struct QNode{
ElementType Data[MaxSize];
int rear;//队列尾巴
int front;//队列头 其实是头一个前一个哈哈哈
};
typedef struct QNode *Queue;
// 环形队列
// 空满都会导致front rear相等 n种状态区分n+1种状态 增加额外的标记 size or tag或者是不放满
void addQ(Queue PtrQ,ElementType X){
//只用数组n-1个空间
//进行判别
if((PtrQ->rear+1)%Maxsize == PtrQ->front){
printf("队列满");
return;
}
PtrQ -> rear = (PtrQ-> rear+1)%Maxsize;
PtrQ -> Data[PtrQ->rear] = item
}
// 出队
elementType deleteQ(Queue PtrQ){
if(PtrQ->front == PtrQ-> rear){
printf(“队列空");return ERROR;
}else{
PtrQ->front = (PtrQ->front +1)%MaxSize;
return PtrQ->Data[PtrQ->front];
}
}
链表实现队列
//定义:单链表的尾巴不适合删除
// 头删 尾入
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{
//代表队列的结构
struct Node *rear;//队尾
struct Node *front;//队头
};
typedef struct QNode *Queue;
Queue PtrQ;
//出队
ElementType DeleteQ(Queue PtrQ){
struct Node *Frontcell
ElementType FrontElem;
if(PtrQ-> front== NULL)
{
printf("队列空");return ERROR;
}
FrontCell = PtrQ->front;
if(PtrQ->front == PtrQ->rear)
PtrQ-> front = PtrQ->rear = NULL;
else
PtrQ->front = PtrQ -> front -> Next;
FrontELem = FrontCell->Data;//需要独立 取出来
free(Frontcell);
return FrontElem;
}
5: 线性表的总结:
多项式相加