线性结构
线性表(Linear List)
由同类型的数据元素构成的有序序列的线性结构
- 元素个数称为线性表的长度
- 线性表没有元素时,称为空表
- 表的起始位置称为表头,表的结束位置称为表尾
###有序线性表
抽象数据类型(ADT)
createNewList(*list)//创建新的线性表
makeListEmpty(*list)//将线性表置空
isEmpty(list)//判断是否为空
getElement(position,list)//获取某个位置的元素
locateElement(value,list)//获取某个值所在的位置
listInsertValue(value,position,list)//将某个值插入到某个位置
listDeleteElement(position,list)//将某个位置的元素删除
listLength(list)//获取线性表的长度
有序线性表结构原型
typedef struct
{
elementType arry[maxSize];
int currentPosition;//当前所在位置(当前长度)
}List;
线性表的链式存储
不要求逻辑上相邻的两个元素在物理上也相邻,插入删除不需要移动数据元素,只需要修改链
结构原型
typedef struct
{
int value;
strcut List *next;
}List;
抽象数据类型(ADT)
listLength(list)//求表长
listFindPosition(list,position)//求某个位置的元素
listFindValue(list,value)//查找某个值,返回指针
listInsertNode(list,position)//将节点插入到某个位置
listDeleteNode(list,position)//删除节点
广义表(多重链表)
- 是线性表的推广
- 线性表的n个元素都是基本的单元素
- 广义表中,不仅可以是单元素,也可以是另一个广义表
结构原型
typedef struct
{
int flag;//用作标记,0为单元素,1为广义表
union
{
listType value;
struct List *gNext;
}gList;
struct List *next;
}List;
多重链表的指针域有多个,包含两个指针域的链表不一定是多重链表,比方说双向链表
栈(stack)
栈(stack),遵循后入先出,先进后出(Last In First Out----LIFO)的基本原则
栈顶为最上面的元素,即最后插入的元素
栈底为最底下的元素,即最先插入的元素
抽象数据类型(ADT)
push()//入栈,添加数据
pop()//出栈,删除并返回栈顶数据
createStack()//创建空栈
stackIsFull()//是否已满
stackIsEmpty()//是否为空
堆栈原型
typedef struct
{
int top;//栈顶
elementType arry[maxSize];//最大元素个数的数组
}stack;
栈
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define maxSize 10
typedef struct
{
int pos;
int a[maxSize];
} stack;
void creatStack(stack *p)
{
p->pos = -1;
}
bool stackIsFull(stack *p)
{
if (p->pos == maxSize - 1)
return true;
return false;
}
void push(stack *p)
{
printf("input value:");
int n;
scanf("%d", &n);
if (stackIsFull(p))
{
printf("stack is full");
return;
} else
{
p->a[++(p->pos)] = n;
}
}
bool stackIsEmpty(stack *p)
{
if (p->pos == -1)
return true;
return false;
}
void pop(stack *p)
{
if (stackIsEmpty(p))
{
printf("Stack is empty");
return;
}
printf("\n%d", p->a[(p->pos)--]);
}
int main()
{
stack list;
creatStack(&list);
for (int i = 0; i < 10; i++)
{
push(&list);
}
push(&list);
for (int i = 0; i < 10; i++)
{
pop(&list);
}
pop(&list);
return 0;
}
第二种链表实现栈
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define maxSize 10
typedef struct
{
int value;
struct stack *next;
} stack;
bool stackIsFull(stack *p)
{
int cnt = 0;
for (; p; p = p->next)
cnt++;
return cnt > maxSize - 1;
}
stack *push(stack *p, int n)
{
if (stackIsFull(p))
{
puts("errrors");
return p;
}
stack *temp = malloc(sizeof(stack));
temp->value=n;
temp->next=p;
puts("success");
return temp;
}
bool stackIsEmpty(stack *p)
{
return p==NULL;
}
stack *pop(stack *p)
{
if(stackIsEmpty(p))
{
puts("stack is empty");
return p;
}
stack *c=p;
printf("%d",c->value);
p=p->next;
free(c);
return p;
}
int main()
{
stack *a=NULL;
for(int i=0;i<11;i++)
{
int n;
scanf("%d",&n);
a=push(a,n);
}
for(int i=0;i<13;i++)
{
a=pop(a);
}
return 0;
}
#队列(queue)
概念
只允许在其中一端插入数据,另一端删除数据的线性表
插入数据称为入队
删除数据称为出队
遵循先入先出(First In First Out)FIFO
**空队列:**是指没有任何元素的队列
**队头:**允许删除元素的一端,靠近队头的第一个元素称为队头元素
**队尾:**允许插入数据的一端,靠近队尾的最后一个元素称为队尾元素
抽象数据类型
createQueue()//创建一个队列 并初始化
freeQueue()//销毁队列
enterQueue()//入队
deQueue()//出队,并删除队头元素
readQueue()//读取队头元素
queueIsEmpty()//队列是否为空
队列的顺序实现
方法1-浪费一个存储空间
#include <stdio.h>
#include<stdbool.h>
#include <stdlib.h>
#define maxSize 10
typedef struct
{
int a[maxSize];
int front, rear;
} queue;
bool isEmpty(queue *p)
{
if (p->front == p->rear)
return true;
return false;
}
void createQueue(queue *p)
{
p->rear = p->front = 0;
}
bool isFull(queue *p)
{
return (p->rear + 1) % maxSize == p->front % maxSize;//因为判断为空的条件是尾部的值等于头部的,只能牺牲一个元素作为判断是否已满的条件
}
bool enQueue(queue *p, int n)
{
if (isFull(p))
return false;
p->a[p->rear] = n;
p->rear = (p->rear + 1) % maxSize;
return true;
}
bool deQueue(queue *p, int *e)
{
if (isEmpty(p))
return false;
*e = p->a[p->front];
p->front = (p->front + 1) % maxSize;
return true;
}
bool readHead(queue *p)
{
if (isEmpty(p))
return false;
printf("%d", p->a[p->front]);
return true;
}
int queueSize(queue p)
{
return (p.rear+maxSize-p.front)%maxSize;
}
int main()
{
queue qu;
createQueue(&qu);
if (isEmpty(&qu))
puts("yes");
for (int i = 0; i < 12; i++)
{
int n;
scanf("%d", &n);
if (enQueue(&qu, n))
printf("success\n");
else
printf("error\n");
}
printf("\n\n\n\n");
if(readHead(&qu))
printf("read success\n");
else
printf("read error\n");
for (int i = 0; i < 12; i++)
{
int n;
if (deQueue(&qu, &n))
{
printf("success\n");
printf("%d\n", n);
printf("len=%d\n",queueSize(qu));
} else
printf("error\n");
}
return 0;
}
第二种-不浪费一个存储空间
#include <stdio.h>
#include<stdbool.h>
#include <stdlib.h>
#define maxSize 10
typedef struct
{
int a[maxSize];
int front, rear,size;
} queue;
bool isEmpty(queue *p)
{
if (p->front == p->rear)
return true;
return false;
}
void createQueue(queue *p)
{
p->size=0;
}
bool isFull(queue *p)
{
return p->size==maxSize;
}
bool enQueue(queue *p, int n)
{
if (isFull(p))
return false;
p->a[p->rear] = n;
p->rear = (p->rear + 1) % maxSize;
p->size++;
return true;
}
bool deQueue(queue *p, int *e)
{
if (isEmpty(p))
return false;
*e = p->a[p->front];
p->front = (p->front + 1) % maxSize;
p->size--;
return true;
}
bool readHead(queue *p)
{
if (isEmpty(p))
return false;
printf("%d", p->a[p->front]);
return true;
}
int queueSize(queue p)
{
return (p.rear+maxSize-p.front)%maxSize;
}
int main()
{
queue qu;
createQueue(&qu);
if (isEmpty(&qu))
puts("yes");
for (int i = 0; i < 12; i++)
{
int n;
scanf("%d", &n);
if (enQueue(&qu, n))
printf("success\n");
else
printf("error\n");
}
printf("\n\n\n\n");
if(readHead(&qu))
printf("read success\n");
else
printf("read error\n");
for (int i = 0; i < 12; i++)
{
int n;
if (deQueue(&qu, &n))
{
printf("success\n");
printf("%d\n", n);
printf("len=%d\n",queueSize(qu));
} else
printf("error\n");
}
return 0;
}
链式队列
带头节点
#include <stdio.h>
#include<stdbool.h>
#include <stdlib.h>
#define maxSize 10
typedef struct queue
{
int value;
struct queue *next;
} queue;
typedef struct
{
queue *front, *rear;
} linkQueue;
void create(linkQueue *pp)
{
pp->front = pp->rear = malloc(sizeof(linkQueue));
pp->front->next = NULL;
}
bool isEmpty(linkQueue *p)
{
if (p->front == p->rear)
return true;
return false;
}
bool enQueue(linkQueue *p)
{
queue *n = malloc(sizeof(queue));
scanf("%d", &n->value);
n->next = NULL;
p->rear->next = n;
p->rear = n;
return true;
}
bool deQueue(linkQueue *p)
{
if (isEmpty(p))
return false;
queue *t = p->front->next;
printf("%d ", t->value);
p->front->next = t->next;
if(p->rear==t)
p->front=p->rear;
free(t);
return true;
}
int main()
{
linkQueue qu;
create(&qu);
for (int i = 0; i < 5; i++)
enQueue(&qu);
for (int i = 0; i < 6; i++)
{
if (deQueue(&qu));
else
printf("error\n");
}
return 0;
}
不带头节点
#include <stdio.h>
#include<stdbool.h>
#include <stdlib.h>
#define maxSize 10
typedef struct queue
{
int value;
struct queue *next;
} queue;
typedef struct
{
queue *front, *rear;
} linkQueue;
void create(linkQueue *pp)
{
pp->front = NULL;
pp->rear = NULL;
}
bool isEmpty(linkQueue *p)
{
if (p->front == NULL)
return true;
return false;
}
bool enQueue(linkQueue *p)
{
queue *n=malloc(sizeof(queue));
n->next=NULL;
scanf("%d", &n->value);
if(isEmpty(p))//因为此时的rear和front都为空,要使rear始终位于最后一个元素,所以要特殊处理
{
p->rear=n;
p->front=n;
}
p->rear->next=n;
p->rear=n;
return true;
}
bool deQueue(linkQueue *p)
{
if (isEmpty(p))
return false;
queue *t=p->front;
printf("%d ",t->value);
p->front=t->next;
free(t);
return true;
}
int main()
{
linkQueue qu;
create(&qu);
for (int i = 0; i < 5; i++)
enQueue(&qu);
for (int i = 0; i < 16; i++)
{
if (deQueue(&qu));
else
printf("error\n");
}
return 0;
}
双端队列
可以从两端进行插入删除,只要是栈能实现的功能,双端队列都能实现
也分为输入受限队列和输出受限队列
即一端只能插入或者删除,另一端可以同时插入删除
Q.E.D.