什么是数据结构
是一门研究数据之间关系的一门学科,主要有两类需要研究的关系:逻辑关系、物理关系
物理关系:数据在内存中的实际关系。
顺序结构:根据数据之间的相对位置确定关系
链式结构:在数据当中再添加一个指针域,用于指向跟它有关系的数据。
逻辑关系:无视物理关系,人为添加的一种关系。
集合:数据之间同属一个集体,除此之外没有任何关系。
表:数据之间存在一对一关系,如:数组(顺序表),链表(链式表)。
树:数据之间存在一对多关系。
图:数据之间存在多对多关系。
注意:我们常说的数据结构指的是逻辑关系,而数据结构在内存中的储存方式,指的是物理关系。
每种逻辑关系采用什么样的物理结构储存并没有明确规定,通常以代码实现的验证、以及时间、空间复杂度的要求,选择最合适的物理结构储存,也有可能是链式和顺序混合存储。
算法
广义:解决特定问题的方法
狭义:数据结构的运算
学习数据结构的三个关键点
1、物理结构
2、逻辑结构:所有的逻辑结构既可以是顺序结构存在,也可以是链式结构存在。
3、结构的运算
数据结构常有的运算:
1、创建数据结构:create
2、销毁数据结构:destroy
3、清除所有元素:clear
4、遍历数据结构:show、print
5、从数据结构中删除一个元素:delete
6、把一个元素插入到数据结构:install
7、修改数据结构中的某个元素:modify
8、查询数据结构中的元素:query、find
9、访问其中一个元素:access
顺序表
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#define TYPE int
//设计顺序表结构:元素之间是连续的
typedef struct Order
{
TYPE* ptr;
int cal;
int cnt;
}Order;
//创建顺序表
Order* create_order(int cal)
{
//给表结构分配内存
Order* order = malloc(sizeof(Order));
//给元素分配内存
order->ptr = malloc(sizeof(TYPE)*cal);
//记录表的容量
order->cal = cal;
//初始化元素的数量
order->cnt = 0;
return order;
}
//销毁顺序表
void destroy_order(Order* order)
{
free(order->ptr);
order->ptr=NULL;
free(order);
order = NULL;
}
//清除表元素
void clear_order(Order* order)
{
order->cnt = 0;
}
//插入元素
bool insert_order(Order* order,int index,TYPE val)
{
if(order->cnt >= order->cal || index >= order->cnt)
{
return false;
}
for(int i=order->cnt; i>index; i--)
{
order->ptr[i] = order->ptr[i-1];
}
order->ptr[index] = val;
order->cnt++;
return true;
}
//删除元素
bool delete_order(Order* order,int index)
{
if(index >= order->cnt)
{
return false;
}
for(int i=0; i<order->cnt-1; i++)
{
order->ptr[i] = order->ptr[i+1];
}
order->cnt--;
return true;
}
//添加元素
bool add_order(Order* order,TYPE val)
{
//判断表是否满
if(order->cnt >= order->cal)
{
return false;
}
//在末尾添加元素
order->ptr[order->cnt++] = val;
return true;
}
//访问元素
bool access_order(Order* order,int index,TYPE* p)
{
if(index >= order->cnt)
{
return false;
}
*p = order->ptr[index];
return true;
}
//修改元素
bool modify_order(Order* order,TYPE old,TYPE new)
{
for(int i=0; i<order->cnt; i++)
{
if(order->ptr[i] == old)
{
order->ptr[i] = new;
return true;
}
}
return false;
}
//查询元素
int query_order(Order* order,TYPE key)
{
for(int i=0; i<order->cnt; i++)
{
if(key == order->ptr[i])
{
return i;
}
}
return -1;
}
//遍历顺序表
void show_order(Order* order)
{
for(int i=0; i<order->cnt; i++)
{
printf("%d ",order->ptr[i]);
}
printf("\n");
}
//排序顺序表
void sort_order(Order* order)
{
for(int i=0; i<order->cnt-1; i++)
{
for(int j=i+1; j<order->cnt; j++)
{
if(order->ptr[j] > order->ptr[i])
{
TYPE temp = order->ptr[i];
order->ptr[i] = order->ptr[j];
order->ptr[j] = temp;
}
}
}
}
int main(int argc,const char* argv[])
{
Order* order = create_order(15);
for(int i=0; i<10; i++)
{
add_order(order,rand()%100);
}
show_order(order);
insert_order(order,1,10001);
show_order(order);
delete_order(order,1);
show_order(order);
int num=0;
access_order(order,0,&num) && printf("access:%d",num);
sort_order(order);
show_order(order);
}
功能被限制的表
栈
只有一个端口进入,元素先进后出FILO
而栈内存正是使用了这种结构管理内存,所以才叫栈内存
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define TYPE int
typedef struct StackOrder
{
TYPE* ptr;
int cal;
int top;
}StackOrder;
//创建桟
StackOrder* create_stack(int cal)
{
StackOrder* stack = malloc(sizeof(StackOrder));
stack->ptr = malloc(sizeof(TYPE)*cal);
stack->cal = cal;
stack->top = -1; //cal|cal-1|0|-1
/*
cal:满减桟
cal-1:空减桟
-1:满增桟
0:空增桟
*/
return stack;
}
//销毁桟
void destroy_stack(StackOrder* stack)
{
free(stack->ptr);
free(stack);
}
//桟空
bool empty_stack(StackOrder* stack)
{
return -1 == stack->top;
}
//桟满
bool full_stack(StackOrder* stack)
{
return stack->top >= stack->cal-1;
}
//入桟
bool push_stack(StackOrder* stack,TYPE val)
{
if(full_stack(stack))
return false;
stack->ptr[++stack->top] = val;
return true;
}
//出桟
bool pop_stack(StackOrder* stack)
{
if(empty_stack(stack))
return false;
stack->top--;
return true;
}
//获取栈顶元素
TYPE top_stack(StackOrder* stack)
{
return stack->ptr[stack->top];
}
int main(int argc,const char* argv[])
{
StackOrder* stack = create_stack(10);
for(int i=0; i<11; i++)
{
bool flag = push_stack(stack,i);
printf("push:%d %s\n",i,flag?"成功":"失败");
}
while(!empty_stack(stack))
{
printf("top:%d ",top_stack(stack));
printf("%s\n",pop_stack(stack)?"成功":"失败");
}
}
队列
把一个表结构限制成有两个端口,一个端口只能进,另一个端口只能出,先进先出FIFO
队头 0
队尾 0
队空 队头==队尾
队满 队尾+1==队头
出队 front = (front+1)%cal
入队 rear = (rear+1)%cal
队头元素 ptr[front]
队尾元素 (cal+rear-1)%cal
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define TYPE int
typedef struct QueueOrder
{
TYPE* ptr;
int cal;
int front;
int rear;
}QueueOrder;
//创建队列
QueueOrder* create_queue(int cal)
{
QueueOrder* queue = malloc(sizeof(QueueOrder));
queue->ptr = malloc(sizeof(TYPE)*cal);
queue->cal = cal;
queue->front = 0;
queue->rear = 0;
return queue;
}
//销毁队列
void destroy_queue(QueueOrder* queue)
{
free(queue->ptr);
free(queue);
}
//队空
bool empty_queue(QueueOrder* queue)
{
return queue->front == queue->rear;
}
//队满
bool full_queue(QueueOrder* queue)
{
return (queue->rear+1)%queue->cal == queue->front;
}
//入队
bool push_queue(QueueOrder* queue,TYPE val)
{
if(full_queue(queue))
return false;
queue->ptr[queue->rear] = val;
queue->rear = (queue->rear+1)%queue->cal;
return true;
}
//出队
bool pop_queue(QueueOrder* queue)
{
if(empty_queue(queue))
return false;
queue->front = (queue->front+1)%queue->cal;
return true;
}
//队头
TYPE front_queue(QueueOrder* queue)
{
return queue->ptr[queue->front];
}
//队尾
TYPE rear_queue(QueueOrder* queue)
{
if(queue->rear)
return queue->ptr[queue->rear-1];
else
return queue->ptr[queue->cal-1];
//return queue->ptr[(queue->rear+queue->cal-1)%queue->cal];
}
int main(int argc,const char* argv[])
{
QueueOrder* queue = create_queue(10);
for(int i=0; i<10; i++)
{
push_queue(queue,i);
printf("rear:%d\n",rear_queue(queue));
}
while(!empty_queue(queue))
{
printf("front:%d\n",front_queue(queue));
pop_queue(queue);
}
}
链式表
元素:由数据域,指针域组成,元素之间使用指针域链接,这种结构叫链式存储结构。
如果元素中只有一个指针域,且指向下一个元素,这样元素之间就只存在一对一关系,这种结构叫链式表。
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define TYPE int
//链表的节点
typedef struct Node
{
TYPE data; //数据域
struct Node* next; //指针域,指向下一个节点
}Node;
//创建节点
Node* create_node(TYPE data)
{
Node* node = malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
//链表
typedef struct List
{
Node* head;
Node* tail;
}List;
//创建链表
List* create_list(void)
{
List* list = malloc(sizeof(List));
list->head = NULL;
list->tail = NULL;
}
//头添加节点
void add_head_list(List* list,TYPE data)
{
Node* node = create_node(data);
if(NULL == list->head)
{
list->head = node;
list->tail = node;
}
else
{
node->next = list->head;
list->head = node;
}
}
//尾添加节点
void add_tail_list(List* list,TYPE data)
{
Node* node = create_node(data);
if(NULL == list->tail)
{
list->head = node;
list->tail = node;
}
else
{
list->tail->next = node;
list->tail = node;
}
}
//头删除节点
void del_head_list(List* list)
{ Node* node = list->head;
if(list->tail == list->head)
{
list->head = NULL;
list->tail = NULL;
}
else
{
list->head = node->next;
}
free(node);
}
//尾删除节点
void del_tail_list(List* list)
{
Node* node = list->tail;
if(list->tail == list->head)
{
list->head = NULL;
list->tail = NULL;
}
else
{
Node* prev = list->head;
while(prev->next != list->tail)
{
prev = prev->next;
}
prev->next = NULL;
list->tail = prev;
}
free(node);
}
//修改
bool modify_list(List* list,TYPE old,TYPE new)
{
for(Node* n=list->head; NULL!=n; n=n->next)
{
if(n->data == old)
{
n->data = new;
return true;
}
}
return false;
}
//查询
bool query_list(List* list,TYPE key)
{
for(Node* n=list->head; NULL!=n; n=n->next)
{
if(key == n->data)
{
return true;
}
}
return true;
}
//长度
size_t len_list(List* list)
{
int len = 0;
for(Node* n=list->head; NULL!=n; n=n->next)
{
len++;
}
return len;
}
//遍历
void show_list(List* list)
{
for(Node* n=list->head; NULL!=n; n=n->next)
{
printf("%d ",n->data);
}
printf("\n");
}
//排序
void sort_list(List* list)
{
for(Node* n1=list->head; list->tail!=n1->next; n1=n1->next)
{
for(Node* n2=n1->next; NULL!=n2; n2=n2->next)
{
if(n1->data < n2->data)
{
TYPE temp = n1->data;
n1->data = n2->data;
n2->data = temp;
}
}
}
}
int main(int argc,const char* argv[])
{
List* list = create_list();
for(int i=0; i<15; i++)
{
add_tail_list(list,i);
}
show_list(list);
del_tail_list(list);
show_list(list);
modify_list(list,7,100);
show_list(list);
printf("len:---%d---",len_list(list));
sort_list(list);
show_list(list);
}