数据 结构

 一组用来保存一种或者多种特定关系的数据的集合(组织和存储数据)

    程序 = 数据结构 + 算法

一、线性结构

1.顺序表:数组

2.链式表:链表

数组和链表的区别:

1. 存储方式

  • 数组:在内存中占用连续的空间。每个元素的地址可以通过基地址和索引计算得出。
  • 链表:由一系列节点组成,每个节点包含数据和指向下一个节点的指针。节点在内存中不需要连续存储,可以分散在不同的内存位置。

2. 大小

  • 数组:大小在创建时固定,无法动态调整。需要预先定义数组的大小。

  • 链表:大小动态可变,可以根据需要添加或删除节点。不需要预先定义大小。

3. 访问效率

  • 数组:支持随机访问,可以通过索引直接访问任意元素,时间复杂度为 O(1)。
  • 链表:只能顺序访问,必须从头节点开始遍历,时间复杂度为 O(n)。

4. 插入和删除操作

  • 数组:插入和删除操作较慢,尤其是在数组中间进行操作时,需要移动大量元素,时间复杂度为 O(n)。
  • 链表:插入和删除操作较快,只需调整指针即可,时间复杂度为 O(1)(在已知位置的情况下)。

5. 内存管理

  • 数组:在创建时分配固定大小的内存,可能会导致内存浪费或不足。
  • 链表:节点在需要时动态分配内存,内存使用更灵活,但需要额外的指针存储开销。

6. 适用场景

  • 数组:适用于需要频繁随机访问的场景,如查找、排序等。
  • 链表:适用于需要频繁插入和删除的场景,如实现队列、栈等数据结构。

(1)单向链表:有头链表、无头链表

   a.结点:  数据域、指针域

(2)有头链表

a.头插

b.尾插

c.头删

d.尾删

#include "link.h"
#include <stdlib.h>
#include <stdio.h>
#ifndef __LINK_H__
#define __LINK_H__

/*链表存储的数据的数据类型*/
typedef int DataType;

/*链表的结点类型*/
typedef struct node
{
	DataType data;      //数据域  
	struct node *pnext; //指针域:指向下一个结点
}Link_Node_t;

/*链表的对象类型*/
typedef struct link
{
	Link_Node_t *phead; //链表头结点地址
	int clen;           //链表当前结点个数
}Link_t;


Link_t *create_link()//创建链表对象
{
	Link_t *plink = (Link_t *)malloc(sizeof(Link_t));
	if (NULL == plink)
	{
		perror("fail malloc");
		return NULL;
	}
	
	plink->phead = NULL;
	plink->clen = 0;

	return plink;
}
int push_link_head(Link_t *plink, DataType data)//头插
{
	Link_Node_t *pnode = (Link_Node_t *)malloc(sizeof(Link_Node_t));
	if (NULL == pnode)
	{
		perror("fail malloc\n");
		return -1;
	}
	pnode->data = data;
	pnode->pnext = NULL;
	pnode->pnext = plink->phead;
	plink->phead = pnode;
	plink->clen++;
	return 0;
}

void traverse_link(Link_t *plink)//遍历
{
    Link_Node_t *p = plink->phead;   
    while(p != NULL)
    {
        printf("%d ",p->data);
        p = p->pnext;
    }
    printf("\n");
}

int push_link_tail(Link_t *plink,DataType data)//尾插
{
    Link_Node_t *pnode = (Link_Node_t *)malloc(sizeof(Link_Node_t));
    if(NULL == pnode)
    {
        perror("fail malloc\n");
        return -1;
    }
	pnode->data = data;
	pnode->pnext = NULL;
    if(plink->phead == NULL)
    {
        plink->phead = pnode;   
    }
    else
    {
        Link_Node_t *p = plink->phead;
        while(p->pnext != NULL)
        {
            p = p->pnext;
        }
        p->pnext = pnode;
    }
    plink->clen++;
    return 0;
}

int pop_link_head(Link_t *plink)//头删
{
    if(NULL == plink->phead)
    {
        return 0;
    }
    else
    {
        Link_Node_t *p = plink->phead;
        plink->phead = plink->phead->pnext;
        free(p);
        plink->clen--;
    }
    return 1;
}

int pop_link_tail(Link_t *plink)//尾删
{
    if(NULL == plink->phead)
    {
        return 0;
    }
    else if(NULL == plink->phead->pnext)
    {
        pop_link_head(plink);
    }
    else
    {
        Link_Node_t *p = plink->phead;
        while(p->pnext->pnext != NULL)
        {
            p = p->pnext;
        }
        free(p->pnext);
        p->pnext = NULL;
        plink->clen--;
        return 1;
    }
}

Link_Node_t *seek_link(Link_t *plink,DataType data)//查找任意节点
{
    Link_Node_t *p = plink->phead;
    while(p != NULL)
    {
        if(p->data == data)
        {
            return p->pnext;
        }
        p = p->pnext;
    }
    return NULL;
}

int change_link(Link_t *plink,DataType data1,DataType data2)//改变节点中的data
{
    Link_Node_t *p = plink->phead;
    while(p != NULL)
    {
        if(p->data == data1)
        {
            p->data = data2;
            return 1;
        }
        p = p->pnext;
    }
    return 0;
}

int destory_link(Link_t *plink)//销毁链表
{
   Link_Node_t *p = plink->phead;
    while(p != NULL)
    {
        pop_link_head(plink);
        p = p->pnext;
    }
    free(plink);
    return 0;
}

Link_Node_t *seek_mid_node(Link_t *plink)//寻找中间节点
{
    if(plink->phead == NULL)
    {
        return NULL;
    }
    else
    {
        Link_Node_t *p = plink->phead;
        int i = (plink->clen) / 2;
        for(int j = 0;j < i;++j)
        {
            p = p->pnext;
        }
        return p;
    }
}

Link_Node_t *seek_counterback_node(Link_t *plink,int k)//寻找倒数节点
{
    if(plink->phead == NULL || k > plink->clen)
    {
        printf("K > node\n");
        return NULL;
    }
    else
    {
        Link_Node_t *p = plink->phead;
        int i = plink->clen - k;
        for(int j = 0;j < i;++j)
        {
            p = p->pnext;
        }
        return p;
    }
}

int pop_node(Link_t *plink,int t)//删除节点
{
    if (t <= 0 || plink->clen < t || plink->phead == NULL) 
    {  
        printf("t error\n");  
        return -1;  
    }  
    Link_Node_t *p = plink->phead;   
    if(t == 1)
    {
        pop_link_head(plink);
    }
    else
    {
        for (int i = 1; i < t - 1; ++i) 
        {  
            if (p->pnext == NULL) 
            {  
                printf("t > nodes\n");  
                return -1;  
            }  
            p = p->pnext;  
        }  
        Link_Node_t *del_node = p->pnext;  
        if (del_node == NULL) 
        {     
            printf("No node to delete\n");  
            return -1;  
        }
        p->pnext = del_node->pnext;
        free(del_node);
        plink->clen--;
    }
    return 0;  
}  

    

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值