Part1 概论
Part2 线性结构
Part3 树形结构
Part4 图形结构
Part5 查找
Part6 排序
线性表、栈(后进先出)、队列(先进先出)、数组
线性表的顺序存储
1.类型定义
2.算法实现
(1)插入
(2)删除
(3)定位
3.算法分析
线性表的链接存储
单链表
1.类型定义
//假设数据元素的类型为DataType,单链表的类型定义如下:
typedef struct node
{
DataType data;
struct node *next;
}Node,*LinkList;
2.初始化
3.求表长
4.读表元素
5.定位
//在带头结点的单链表上实现的算法为:
int LocateLinkList(LinkList head,DataType x)
//求链表中值为x的结点的序号,如不存在,返回0
{
Node *p; //p是工作指针
p=head->next; //初始值p指向首结点
int i=0; //i代表节点的序号,这里置初值为0
while((p!=NULL)&&(p->data!=x)) //访问链表
{
i++;
p=p->next; //p移至下一个结点
}
if(p!=NULL) return i+1;
else return 0;
}
6.查找
//在带头结点的单链表上实现的算法为:
Node * GetLinkList(LinkList head,int i)
//在单链表中寻找第i个结点元素,返回指向该结点的指针,否则返回NULL
{
Node *p; //p是工作指针
p=head->next; //初始值p指向首结点
int cnt=1;
while((p!=NULL) && (cnt<i)) //当未找到第i个结点且未到尾结点时,继续后移
{
cnt++;
p=p->next;
}
if(i==cnt) return p; //找到第i个结点
else return NULL;
}
7.插入
//在带头结点的单链表上实现的算法为:
void InsertLinkList(LinkList head,DataType x,int i)
//在单链表中的第i个数据元素结点之前插入一个值为x的新结点
{
Node *p,*q; //p为工作指针,q为新结点
if(i==1) p=head;
else p=GetLinkList(head,i-1);
while(p!=NULL)
{
q=malloc(sizeof(Node)); //生成新结点
q->data=x;
q->next=p->next;
p->next=q;
}
else exit("找不到插入位置")
}
8.删除
//在带头结点的单链表上实现的算法为:
void DeleteLinkList(LinkList head,int i)
//删除链表中第i个结点
{
Node *p,*r; //p为待删结点的直接前驱,r为待删结点
if(i==1) p=head;
else p=GetLinkList(head,i-1) //先找到待删结点的直接前驱
if((p!=NULL)&&(p->next!=NULL)) //若待删结点且直接前驱都存在
{
r=p->next; //r指向待删结点
p->next=r->next; //移出待删结点
free(r); //释放已移出结点r的空间
}
else exit("找不到要删除的结点"); //结点不存在
}
9.建表
- 头插法
- 尾插法
10.删除重复结点
循环链表
单项循环链表
双向循环链表
1.类型定义
2.初始化
3.求表长
4.定位
5.插入
6.删除
栈的顺序实现
1.顺序栈的类型定义
const int maxsize=6; //顺序栈的容量
typedef struct seqstack
{
DataType data[maxsize]; //存储栈中数据元素的数组
int top; //标志栈顶位置的变量
}SeqStk;
2.初始化
int InitStack(SeqStk *stk)
{
stk->top=0;
return 1;
}
3.判栈空
int EmptyStack(SeqStk *stk)
//若栈为空,返回1,否则返回0
{
if(stk->top==0) return 1;
else return 0;
}
4.进栈
int Push(SeqStk *stk,DataType x)
//若栈未满,可进栈,否则提示出错
{
if(stk->top=maxsize-1)
{
error("栈已满");
return 0;
}
else{
stk->top++; //top值加1
stk->data[stk->top]=x; //元素进栈
return 1;
}
}
5.出栈
int Pop(SeqStk *stk)
{
if(EmptyStack(stk))
{
error("下溢");
return 0;
}
else
{
stk->top--; //top值减1
}
}
6.取栈顶元素
DataType GetTop(SeqStk *stk)
{
if(EmptyStack(stk)) //栈空
return NULLData;
else
return stk->data[stk->top]; //返回栈顶数据元素
}
7.双栈⭐⭐
栈的链式实现
1.链栈的类型定义
typedef struct node
{
DataType data;
struct node *next;
}Lkstk;
2.初始化
void InitStack(LkStk *LS)
{
LS=(LkStk *)malloc(sizeof(LkStk));
LS->next=NULL; //建立一个空栈
}
3.判栈空
int EmptyStack(LkStk *LS)
{
if(Ls->next==null) return 1;
else return 0;
}
4.进栈
void Push(LkStk *LS,DataType x)
{
LkStk *temp;
temp=(LkStk *)malloc(sizeof(LkStk));
temp->data=x;
temp->next=LS->next;
LS->next=temp;
}
5.出栈
int Pop(LkStk *LS)
{
if(!EmptyStack(LS))
{
LkStk *temp;
temp=LS->next;
Ls->next=temp->next;
free(temp);
return 1;
}
else return 0;
}
6.获取栈顶元素
DataType GetTop(LkStk *LS)
{
if(!EmptyStack(LS)) return LS->next->data;
else return NULLData;
}
7.链表逆置
LkStk * reverseList(LkStk *head)
{
LkStk *p,*q;
p=head->next; //p指向原链表首结点
head->next=null; //逆置链表初始为空
while(p!=NULL) //遍历原链表,直至为空
{
q=p; //q指向原链表的首结点
p=p->next; //p指向原链表的下一个结点
q->next=head->next;
head->next=q; //“头插”到逆置链表中,q成为逆置链表的“新”的第一个结点
}
return head;
}
队列的顺序实现
1.循环队列的类型定义
typedef struct cycqueue
{
DataType data[maxsize];
int front,rear;
}CycQue;
CycQue CQ;
2.初始化
void InitQueue(CycQue CQ)
{
CQ.front=0;
CQ.rear=0;
}
3.判队列空
int EmptyQueue(CycQue CQ)
{
if(CQ.front==CQ.rear)
return 1; //队列为空,返回1
else
return 0; //队列不为空,返回0
}
4.入队列
int EnQueue(CycQue CQ, DataType x)
{
if((CQ.rear+1)%maxsize==CQ.front)
{
error("队列满");
return 0;
}
else
{
CQ.rear=(CQ.rear+1)%maxsize;
CQ.data[CQ.rear]=x;
return 1;
}
}
5.出队列
int OutQueue(CycQue CQ)
{
if(EmptyQueue(CQ))
{
error("队列空");
return 0;
}
else
{
CQ.front=(CQ.front+1)%maxsize;
return 1;
}
}
6.取队列首元素
DataType GetHead(CycQue CQ)
{
if(EmptyQueue(CQ))
return NULLData;
else
return CQ.data[(CQ.front+1)%maxsize];
}
队列的链式存储
1.链接队列的类型定义
typedef struct LinkQueueNode
{
DataType data;
struct LinkQueueNode *next;
}LkQueNode;
typedef struct LkQueue
{
LkQueNode *front,*rear;
}LkQue;
LkQue LQ;
2.初始化
void InitQueue(LkQue *LQ)
{
LkQueNode *temp;
temp=(LkQueNode *)malloc(sizeof(LkQueNode));
LQ->front=temp;
LQ->rear=temp;
(LQ->front)->next=NULL;
}
3.判队列空
int EmptyQueue(LkQue LQ)
{
if(LQ.rear==LQ.front)
return 1;
else return 0;
}
4.入队列
//入链接队列就是新建一个新的结点,把新的结点放在尾结点后插入
void EnQueue(LkQueue *LQ, DataType x)
{
LkQueNode *temp;
temp=(LkQueNode *)malloc(sizeof(LkQueNode));
temp->data=x;
temp->next=NULL;
(LQ->rear)->next=temp; //新结点入队列
LQ->rear=temp; //置新的队列尾结点
}
5.出队列
int OutQueue(LkQue *LQ)
{
if(EmptyQueue(LQ))
{
error("队列空");
return 0;
}
else
{
LinkQueueNode *temp;
temp=(LQ->front)->next; //temp指向首结点
(LQ->front)->next=temp->next; //修改头结点的指针域指向新的首结点
if(temp->next)
LQ->rear=LQ->front; //无首结点时,front和rear都指向头结点
free(temp);
return 1;
}
}
6.取队列首元素
DataType GetHead(LkQue LQ)
{
if(EmptyQueue(LQ))
{
error("队列空");
return NULLData;
}
else
{
LinkQueueNode *temp;
temp=(LQ.front)->next;
return temp->data;
}
}