数据结构day01--------顺序表、单向链表

目录

数据结构概念:

数据结构学什么?

数据结构按照逻辑关系分类:

数据结构按照存储关系分类:

数据结构按照算法来分类:

线性表 :

顺序表:

    1* 数组实现:

    2* 数组:

    3* 高级货:

顺序表的优缺点:

链表:

单向链表:

单向链表的‘增’‘删’‘改’‘查’操作

link.c文件

link.h文件

main.c文件

Makefile   文件


数据结构概念:


    *概念:
        *数据:
            一切可见不可见抽象事务都是数据
        *结构:
            关系
            
========


数据结构学什么?


    *研究数据之间的关系                ----》逻辑关系
    *将该关系保存到计算机中            ----》存储关系
    *通过计算机手段修改这种关系        ----》算法(增删改查)
    
========


数据结构按照逻辑关系分类:


    线性关系:(一对一的关系)
        有且仅有一个前驱节点和一个后继节点(首尾除外)
        *包含:
            线性表
            栈
            队列
    非线性关系:
        不仅仅只有一个前驱节点和一个后继节点
        (一对多) : 树 ----》 二叉树
        (多对多) : 图 
        
=========


数据结构按照存储关系分类:


    *顺序存储
        数据紧挨保存在一块连续的空间中
    *链式存储
        数据独立存在随机存放,然后通过指针的方式链接起来
        
=========


数据结构按照算法来分类:


    广义的算法:
        时间和空间
    狭义的算法:
        增删改查
        
============================


线性表 :


    线性表按照顺序存储方式:
        顺序表 : 
    
    线性表按照链式存储方式:
        链表:单向,双向,内核

============================


顺序表:


    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


    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值