目录
数据结构概念:
*概念:
*数据:
一切可见不可见抽象事务都是数据
*结构:
关系
========
数据结构学什么?
*研究数据之间的关系 ----》逻辑关系
*将该关系保存到计算机中 ----》存储关系
*通过计算机手段修改这种关系 ----》算法(增删改查)
========
数据结构按照逻辑关系分类:
线性关系:(一对一的关系)
有且仅有一个前驱节点和一个后继节点(首尾除外)
*包含:
线性表
栈
队列
非线性关系:
不仅仅只有一个前驱节点和一个后继节点
(一对多) : 树 ----》 二叉树
(多对多) : 图
=========
数据结构按照存储关系分类:
*顺序存储
数据紧挨保存在一块连续的空间中
*链式存储
数据独立存在随机存放,然后通过指针的方式链接起来
=========
数据结构按照算法来分类:
广义的算法:
时间和空间
狭义的算法:
增删改查
============================
线性表 :
线性表按照顺序存储方式:
顺序表 :
线性表按照链式存储方式:
链表:单向,双向,内核
============================
顺序表:
1* 数组实现:
int arr[10000]; //2个数据
----》 遍历有问题
2* 数组:
struct seq{
int arr[10]; //数据存储的数组
int len; //记录已经存入数据的个数
}
3* 高级货:
struct seq{
int *data; //保存堆返回的地址
int len; //记录已经存入数据的个数
int size; //数组的元素总个数
}
顺序表的优缺点:
*优点:数据查询和替换 非常 快 (通过下标就搞定)
*缺点:添加和删除操作需要数据不断移动
====================
为了克服 顺序的 缺点: 引入链表
========
链表:
*线性结构(表)按照链式存储方式,每个数据都是独立的节点,通过指针链接起来
*链表都有一个表头(数据域是无效的)----称之为 头节点
* 分类:
单向(循环)链表
双向(循环)链表
内核链表
===============
单向链表:
typedef struct xx datatype;
struct link{
datatype data; //数据域
struct link *next; //指针域
};
头插:插在整个有效链表的第一个,也就是插在头的后面
尾插:插在最后一个节点的后面
单向链表的‘增’‘删’‘改’‘查’操作
link.c文件
/**
*******************************************
*
*@Code title 单向链表 增删改查
*
********************************************
*/
#include "link.h"
#include <stdlib.h>
/* 单向链表的 增删改查 操作 */
/**
***********************************
*@brief 一个节点插在另外一个节点的后面
*@param p node 两个节点,node插在p的后面
*@retval None
***********************************
*/
static void insert_behind(link_t *p,link_t *node)
{
node->next = p->next;
p->next = node;
}
/**
***********************************
*@brief 将p节点的后面那个节点截切出来
*@param p
*@retval link_t * 被剪切出来的节点
***********************************
*/
static link_t *cut_behind(link_t *p)
{
link_t *node = p->next;
p->next = node->next;
return node;
}
/**
***********************************
*@brief 将p节点的后面那个节点更新为new
*@param p new 2个节点
*@retval link_t * 被替换出来的节点
***********************************
*/
static link_t *updata_behind(link_t *p,link_t *new)
{
link_t *node = p->next;
new->next = node->next;
p->next = new;
return node;
}
/**
***********************************
*@brief 初始化 (创建头节点)
*@param None
*@retval link_t * :
* 成功返回地址
* 失败返回NULL
***********************************
*/
link_t *link_init(void)
{
link_t *p = (link_t *)malloc(sizeof(link_t));
if(p==NULL){
perror("malloc error");
return NULL;
}
p->next = NULL;
return p;
}
/**
***********************************
*@brief 插入_头插
*@param p : 头节点
*@param d : 需要插入的数据
*@retval None;
***********************************
*/
void link_add_head(link_t *p,datatype d)
{
//创建新的节点
link_t *node = link_init();
if(node==NULL){
printf("创建新节点失败\n");
return;
}
node->data = d;
//将新的节点插在头的后面
insert_behind(p,node);
}
/**
***********************************
*@brief 插入_尾插
*@param p : 头节点
*@param d : 需要插入的数据
*@retval None
***********************************
*/
void link_add_tail(link_t *p,datatype d)
{
//创建新的节点
link_t *node = link_init();
if(node==NULL){
printf("创建新节点失败\n");
return;
}
node->data = d;
//找到最后一个节点
while(p->next!=NULL)
p = p->next;
//将新的节点插在头的后面
insert_behind(p,node);
}
/**
***********************************
*@brief 删除
*@param p : 头节点
*@param d : 需要删除的数据
*@retval None
***********************************
*/
void link_del(link_t *p,datatype d)
{
link_t *node = NULL;
while(p->next!=NULL){
if(p->next->data==d){
node = cut_behind(p);
node->next = NULL; //保证安全
free(node);
continue;
}
p = p->next;
}
}
/**
***********************************
*@brief 修改
*@param p : 头节点
*@param d : 需要删除的数据
*@retval None
***********************************
*/
void link_update(link_t *p,datatype old,datatype new)
{
link_t *new_node = NULL;
link_t *old_node = NULL;
//遍历查询old
while(p->next!=NULL){
if(p->next->data == old){
//通过new 创建新的节点
new_node = link_init();
if(new_node==NULL){
printf("创建新节点失败\n");
return;
}
new_node->data = new;
// new节点替换old
old_node = updata_behind(p,new_node);
// 将old节点释放
old_node->next = NULL;
free(old_node);
}
p = p->next;
}
}
/**
***********************************
*@brief 遍历
*@param p : 头节点
*@retval None
***********************************
*/
void display(link_t *p)
{
printf("遍历结果为:");
while(p->next!=NULL){
p = p->next;
printf("%d ",p->data);
}
printf("\n");
}
link.h文件
#ifndef __LINK_H
#define __LINK_H
#include <stdio.h>
typedef int datatype;
typedef struct link{
datatype data; //数据域
struct link *next; //指针域
} link_t;
extern link_t *link_init(void);
extern void link_add_head(link_t *p,datatype d);
extern void link_add_tail(link_t *p,datatype d);
extern void link_del(link_t *p,datatype d);
extern void link_update(link_t *p,datatype old,datatype new);
extern void display(link_t *p);
#endif
main.c文件
#include "link.h"
int main(void)
{
//初始化
link_t * p = link_init();
if(p==NULL)
return -1;
printf("%p\n",p);
datatype d;
int ret;
printf("开始尾插\n");
while(1){
ret = scanf("%d",&d);
if(!ret)
break;
link_add_tail(p,d);
display(p);
}
getchar();
printf("开始逆序\n");
while(p->next!=NULL){
link_add_tail(p,d);
display(p);
}
printf("开始删除\n");
while(1){
ret = scanf("%d",&d);
if(!ret)
break;
link_del(p,d);
display(p);
}
getchar();
printf("开始替换\n");
datatype old,new;
while(1){
ret = scanf("%d %d",&old,&new);
if(!ret)
break;
link_update(p,old,new);
display(p);
}
}
Makefile 文件
app:link.c test.c link.h
gcc $^ -o $@ -Wall -O0 -g
顺序表的‘增’‘删’‘改’‘查’操作
seq.c
#include "seq.h"
#include <stdlib.h>
/* 顺序表 增删改查 */
/**
***********************************
*@brief 初始化
*@param None
*@retval struct seq * :
* 成功返回地址
* 失败返回NULL
***********************************
*/
struct seq *seq_init(void)
{
//在堆中创建结构体对象
struct seq *p = (struct seq *)malloc(sizeof(struct seq));
if(p==NULL){
perror("malloc error");
return NULL;
}
//给对象成员赋值
p->len = 0;
p->size = N;
p->data = (datatype *)malloc(sizeof(datatype)*(p->size));
if(p->data == NULL){
perror("malloc error");
return NULL;
}
return p;
}
/**
***********************************
*@brief 添加
*@param p : 顺序表
*@param d : 数据
*@param loc : 下标
*@retval None
***********************************
*/
void seq_add(struct seq *p,datatype d,int loc)
{
datatype *temp;
//判断位置是否合理
if(loc<0 || loc>p->len){
printf("sorry!位置不合法\n");
return;
}
//判断当前数组是否存满
if(p->len == p->size){
p->size += N;
temp = (datatype *)realloc(p->data,sizeof(datatype)*(p->size));
if(temp==NULL){
perror("realloc error");
return;
}
p->data = temp;
printf("扩容成功\n");
}
//保存数据
int i;
for(i=p->len-1;i>=loc;i--){
p->data[i+1]=p->data[loc];
}
p->data[loc]=d;
p->len++;
}
/**
***********************************
*@brief 删除
*@param p : 顺序表
*@param d : 需要删除的数据
*@retval None
***********************************
*/
void seq_del(struct seq *p,datatype d)
{
datatype *temp;
int i=0,j;
while(i<p->len){
//缩容
if((p->size-p->len)>N){
p->size-=N;
temp = (datatype *)realloc(p->data,sizeof(datatype)*(p->size));
if(temp==NULL){
perror("realloc error");
return;
}
p->data = temp;
printf("缩容成功\n");
}
if(p->data[i]==d){
//往前移动
for(j=i+1;j<=p->len-1;j++){
p->data[j-1]=p->data[j];
}
p->len--;
continue;
}
i++;
}
//换序
/*int j,k,z;
for(i=0;i<=len;i++)
{
for(k=1;k<=len;k++)
{
if(p->date[i]>p->date[k])
{
z=p->date[i];
p->date[i]=p->date[k];
p->date[k]=z;
}
}
}
printf("复数换序完成\n");*/
}
/**
***********************************
*@brief 替换
*@param p : 顺序表
*@param old : 需要替换的数据
*@param new : 新的数据
*@retval None
***********************************
*/
/*void seq_update(struct seq *p,datatype old,datatype new)
{
int i;
for(i=0;i<p->len;i++){
if(p->data[i]==old){
p->data[i]=new;
}
}
}*/
/**
***********************************
*@brief 遍历
*@param p : 顺序表
*@retval None
***********************************
*/
void display(struct seq *p)
{
int i;
printf("遍历结果为:");
for(i=0;i<p->len;i++){
printf("%d ",p->data[i]);
}
printf("\n");
}
seq.h
#ifndef __SEQ_H
#define __SEQ_H
#include <stdio.h>
#define N 8
typedef int datatype;
struct seq{
datatype *data; //保存堆返回的地址
int len; //记录已经存入数据的个数
int size; //数组的元素总个数
};
extern struct seq *seq_init(void);
extern void seq_add(struct seq *p,datatype d,int loc);
extern void seq_del(struct seq *p,datatype d);
extern void seq_update(struct seq *p,datatype old,datatype new);
extern void display(struct seq *p);
#endif
test.c
#include "seq.h"
int main(void)
{
//初始化
struct seq *p = seq_init();
if(p==NULL)
return -1;
printf("%p\n",p);
datatype d;
int loc=0;
int ret;
int i;
//添加数据
while(1){
ret = scanf("%d ",&d);
if(ret==0)
break;
for(i=p->len;i>=0;i--)
{
if(d>p->data[i])
{
seq_add(p,d,i);
p->len++;
break;
}
}
seq_add(p,d,loc);
display(p);
}
getchar();
printf("准备删除\n");
/*while(1){
ret = scanf("%d",&d);
if(ret==0)
break;
seq_del(p,d);
display(p);
}
getchar();
printf("准备替换\n");
datatype old,new;
while(1){
ret = scanf("%d %d",&old,&new);
if(ret==0)
break;
seq_update(p,old,new);
display(p);
}
*/
return 0;
}
Makefile
app:seq.c test.c seq.h
gcc $^ -o $@ -Wall -O0 -g