数据结构学习入门

1、基本概念
数据:如int a;
数据对象:性质相同的数据元素的集合,如int array[10];
数据元素:组成数据的基本单元(一个一个的结点),如array[0] array[1];
数据项:如

struct Teacher
{
    int age;//即是数据项
    char name[64];//即是数据项
}

数据结构(常见有数组、链表、树、图):研究结点和结点之间的关系,如:散列、1:1、1:N、N:N
存储结构可分为:顺序、链式、索引(跟目录的功能类似)、散列(应用于百度网盘上传时,当进行上传操作时,首先检测是否有相同的文件存在,若有,直接生成链接指向即可。如今的算法有md5、sha1)
数据的操作(5种):插删改查排
O()表示法用来表示算法的复杂度,往往只关注操作数量的最高次数。
复杂度分为时间复杂度和空间复杂度。
空间换时间:如求出一个数组中出现次数最多的数字:
—-》方法:遍历数组,开辟一个空间数组,用来存放每一个数字出现的次数,如1的次数存放到num[0]中,i的次数存放到num[i-1]中(每出现一次i,num[i-1]++),然后求出num[]的最大值,就可知道出现次数最多的那个数。
2、线性表

//*****线性表顺序储存*****///
//在结构体中套1级指针
//
typedef struct _tag_SeqList
{
    int length;
    int capacity;
    unsigned int *node;   //int* node[]
}TSeqList;
//链表的创建
SeqList* SeqList_Create(int capacity)
{
    int ret = 0;
    TSeqList *tmp = NULL;

    tmp = (TSeqList *)malloc(sizeof(TSeqList));//先创建头结点
    if (tmp == NULL)
    {
        ret = -1;
        printf("func SeqList_Create() err:%d \n", ret);
        return NULL;
    }
    memset(tmp, 0, sizeof(TSeqList));

    //根据capacity 的大小分配节点的空间
    tmp->node = (unsigned int *)malloc(sizeof(unsigned int *) * capacity);
    if (tmp->node  == NULL)
    {
        ret = -2;
        printf("func SeqList_Create() err: malloc err %d \n", ret);
        return NULL;
    }
    tmp->capacity = capacity;
    tmp->length = 0;
    return tmp;
}
//开辟内存时进行了两次,所以释放时也应该进行两次
void SeqList_Destroy(SeqList* list)
{
    TSeqList *tlist = NULL;
    if (list == NULL)
    {
        return ;
    }
    tlist = (TSeqList *)list;
    if (tlist->node != NULL)
    {
        free(tlist->node);
    }

    free(tlist);

    return ;
}

//清空链表 //回到初始化状态
void SeqList_Clear(SeqList* list)
{
    TSeqList *tlist = NULL;
    if (list == NULL)
    {
        return ;
    }
    tlist = (TSeqList *)list;
    tlist->length = 0; 
    return ;
}

int SeqList_Length(SeqList* list)
{
    TSeqList *tlist = NULL;
    if (list == NULL)
    {
        return -1;
    }
    tlist = (TSeqList *)list;
    return tlist->length;
}

int SeqList_Capacity(SeqList* list)
{

    TSeqList *tlist = NULL;
    if (list == NULL)
    {
        return -1;
    }
    tlist = (TSeqList *)list;
    return tlist->capacity;
}
//先进行元素后移,再插入元素
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
    int i =0, ret = 0;
    TSeqList *tlist = NULL;

    if (list == NULL || node==NULL ||  pos<0)
    {
        ret = -1;
        printf("fun SeqList_Insert() err:%d \n", ret);
        return ret;
    }
    tlist = (TSeqList*)list;

    //判断是不是满了
    if (tlist->length >= tlist->capacity)
    {
        ret = -2;
        printf("fun SeqList_Insert() (tlist->length >= tlist->capacity) err:%d \n", ret);
        return ret;
    }

    //容错修正  6个长度 容量20;用户pos10位置插入(可通过容错修正为紧接着最后一个元素插入)..
    if (pos>=tlist->length)
    {
        pos = tlist->length; //
    }

    //1 元素后移
    for(i=tlist->length; i>pos; i--)
    {
        tlist->node[i] = tlist->node[i-1];
        //a[7] = a[6]
    }
    // i = 3
    // 2插入元素
    tlist->node[i] = (unsigned int )node;
    tlist->length ++;
    return 0;
}

SeqListNode* SeqList_Get(SeqList* list, int pos)
{
    int i =0;
    SeqListNode *ret = 0;
    TSeqList *tlist = NULL;

    if (list == NULL || pos<0)
    {
        printf("fun SeqList_Get() err:%d \n", ret);
        return NULL;
    }
    tlist = (TSeqList*)list;

    ret = (void *)tlist->node[pos];
    return ret;
}

SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
    int i = 0;
    SeqListNode *ret = 0;
    TSeqList *tlist = NULL;

    if (list == NULL ||  pos<0) //检查
    {
        printf("fun SeqList_Delete() err:%d \n", ret);
        return NULL;
    }
    tlist = (TSeqList*)list;

    ret = (SeqListNode *)tlist->node[pos]; //缓存pos的位置

    for (i=pos+1; i<tlist->length; i++)  //pos位置后面的元素前移
    {
        tlist->node[i-1] = tlist->node[i];
    }
    tlist->length --;
    return ret;
}

这里写图片描述
链表技术领域的推演
这里写图片描述
链表的插入
这里写图片描述
链表的删除
注:指向头结点的指针循环遍历时:
—-》遍历第一次,指向位置0;
—-》遍历第二次,指向位置1;
—-》遍历第n次,指向位置n-1;
—》所以,如果想要知道位置n的元素,需要最后加上ret=current->next

/****线性表的链式储存*****/
让一个结构体单元包含一个线性表结点,线性表结点位于结构体单元的首地址,也即是实现了二级指针。
指针指向谁,就把谁的地址赋给指针;
分清楚链表的操作逻辑和辅助指针变量之间的关系。
typedef struct _tag_LinkListNode
{
    struct _tag_LinkListNode * next;
}LinkListNode;

typedef struct _tag_LinkList
{
    LinkListNode header;
    int length;
}TLinkList;

LinkList* LinkList_Create()
{
    TLinkList *ret = NULL;
    ret = (TLinkList *)malloc(sizeof(TLinkList ));
    memset(ret, 0, sizeof(TLinkList));
    ret->length  = 0;
    ret->header.next = NULL;
}

void LinkList_Destroy(LinkList * list)
{
    if(list != NULL)
    {
        free(list);
        list = NULL;
    }
}

//让链表恢复到初始化状态
void LinkList_Clear(LinkList* list)
{
    TLinkList *tList = NULL;
    if(list == NULL)
    {
        return;
    }
    tList = (TLinkList *)list;
    tList->length = 0;
    tList->header.next = NULL;
    return;
}

int LinkList_Length(LinkList* list)
{
    TLinkList *tList = NULL;
    if(list == NULL)
    {
        return;
    }
    tList = (TLinkList *)list;
    return tList->length;
}

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
{
    int ret = 0;
    LinkListNode *current = NULL;
    TLinkList &tList = NULL;
    if(list == NULL || node == NULL || pos < 0)
    {
        ret = 0;
        printf("func LinkList_Insert() err:%d\n", ret);
        return ret;
    }
    tList = (TLinkList *)list;
    current = &(tList->header);//让辅助指针变量指向链表的头部
    for(i=0; i<pos && current->next != NULL; i++)
    {
        current = current->next;
    }
    //让node连接后续链表
    node->next = current->next;
    //让前面的链表连接新的node节点
    current->next = node;
    tList->length ++;
    return 0;
}

LinkListNode* LinkList_Get(LinkList* list, int pos)
{
    int ret = 0,i = 0;
    LinkListNode *current = NULL;
    TLinkList &tList = NULL;
    if(list == NULL || node == NULL || pos < 0)
    {
        ret = 0;
        printf("func LinkList_Insert() err:%d\n", ret);
        return ret;
    }
    tList = (TLinkList *)list;
    current = &(tList->header);
    for(i=0; i<pos && current->next != NULL; i++)//跳pos次
    {
        current = current->next;
    }
    return current->next;
}

LinkListNode* LinkList_Delete(LinkList* list, int pos)
{
    int i=0;
    LinkListNode *current = NULL;
    LinkListNode *ret = NULL;
    TLinkList &tList = NULL;
    if(list == NULL ||  pos < 0)
    {
        ret = 0;
        printf("func LinkList_Delete() err:%d\n", ret);
        return ret;
    }
    tList = (TLinkList *)list;
    current = &(tList->header);//让辅助指针变量指向链表的头部
    for(i=0; i<pos && current->next != NULL; i++)
    {
        current = current->next;
    }
    ret = current->next;//缓存被删除结点
    //连线
    current->next = ret->next;
    tList->length --;
    return 0;   
}


循环链表的插入算法

/***循环链表**/
typedef struct _tag_CircleListNode
{
    struct _tag_CircleListNode * next;
}CircleListNode;

#include <stdio.h>
#include <malloc.h>
#include "CircleList.h"

typedef struct _tag_CircleList
{
    CircleListNode header;
    CircleListNode* slider;//设置的一个尾结点,指向尾部
    int length;
} TCircleList;

CircleList* CircleList_Create() // O(1)
{
    TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));
    if (ret == NULL)
    {
        return NULL;
    }

    ret->length = 0;
    ret->header.next = NULL;
    ret->slider = NULL;
    return ret;
}

void CircleList_Destroy(CircleList* list) // O(1)
{
    if (list == NULL)
    {
        return ;
    }
    free(list);
}

void CircleList_Clear(CircleList* list) // O(1)
{
    TCircleList* sList = (TCircleList*)list;
    if (sList == NULL)
    {
        return ;
    }
    sList->length = 0;
    sList->header.next = NULL;
    sList->slider = NULL;
}

int CircleList_Length(CircleList* list) // O(1)
{
    TCircleList* sList = (TCircleList*)list;
    int ret = -1;
    if (list == NULL)
    {
        return ret;
    }
    ret = sList->length;
    return ret;
}

int CircleList_Insert(CircleList* list, CircleListNode* node, int pos) // O(n)
{ 
    int ret = 0, i=0;
    TCircleList* sList = (TCircleList*)list;

    if (list == NULL || node== NULL || pos<0)
    {
        return -1;
    }
    //if( ret )
    {
        CircleListNode* current = (CircleListNode*)sList;

        for(i=0; (i<pos) && (current->next != NULL); i++)
        {
            current = current->next;
        }

        //current->next 0号节点的地址
        node->next = current->next; //1
        current->next = node; //2

        //若第一次插入节点
        if( sList->length == 0 )
        {
            sList->slider = node;
        }

        sList->length++;

        //若头插法 current仍然指向头部
        //(原因是:跳0步,没有跳走)
        if( current == (CircleListNode*)sList )
        {
            //获取最后一个元素
            CircleListNode* last = CircleList_Get(sList, sList->length - 1); 
            last->next = current->next; //3
        }
    }

    return ret;
}

CircleListNode* CircleList_Get(CircleList* list, int pos) // O(n)
{
    TCircleList* sList = (TCircleList*)list;
    CircleListNode* ret = NULL;
    int i = 0;

    if (list==NULL || pos<0)
    {
        return NULL;
    }
    //if( (sList != NULL) && (pos >= 0) && (sList->length > 0) )
    {
        CircleListNode* current = (CircleListNode*)sList;

        for(i=0; i<pos; i++)
        {
            current = current->next;
        }

        ret = current->next;
    }

    return ret;
}

CircleListNode* CircleList_Delete(CircleList* list, int pos) // O(n)
{
    TCircleList* sList = (TCircleList*)list;
    CircleListNode* ret = NULL;
    int i = 0;

    if( (sList != NULL) && (pos >= 0) && (sList->length > 0) )
    {
        CircleListNode* current = (CircleListNode*)sList;
        CircleListNode* last = NULL;

        for(i=0; i<pos; i++)
        {
            current = current->next;
        }

        //若删除第一个元素(头结点)
        if( current == (CircleListNode*)sList )
        {
            last = (CircleListNode*)CircleList_Get(sList, sList->length - 1);
        }

        //求要删除的元素
        ret = current->next;
        current->next = ret->next;

        sList->length--;

        //判断链表是否为空
        if( last != NULL )
        {
            sList->header.next = ret->next;
            last->next = ret->next;
        }

        //若删除的元素为游标所指的元素
        if( sList->slider == ret )
        {
            sList->slider = ret->next;
        }

        //若删除元素后,链表长度为0
        if( sList->length == 0 )
        {
            sList->header.next = NULL;
            sList->slider = NULL;
        }
    }

    return ret;
}

CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node) // O(n)
{
    TCircleList* sList = (TCircleList*)list;
    CircleListNode* ret = NULL;
    int i = 0;

    if( sList != NULL )
    {
        CircleListNode* current = (CircleListNode*)sList;

        //查找node在循环链表中的位置i
        for(i=0; i<sList->length; i++)
        {
            if( current->next == node )
            {
                ret = current->next;
                break;
            }

            current = current->next;
        }

        //如果ret找到,根据i去删除    
        if( ret != NULL )
        {
            CircleList_Delete(sList, i);
        }
    }

    return ret;
}

CircleListNode* CircleList_Reset(CircleList* list) // O(1)
{
    TCircleList* sList = (TCircleList*)list;
    CircleListNode* ret = NULL;

    if( sList != NULL )
    {
        sList->slider = sList->header.next;
        ret = sList->slider;
    }

    return ret;
}

CircleListNode* CircleList_Current(CircleList* list) // O(1)
{
    TCircleList* sList = (TCircleList*)list;
    CircleListNode* ret = NULL;

    if( sList != NULL )
    {
        ret = sList->slider;
    }

    return ret;
}

//把当前位置返回,并且游标下移
CircleListNode* CircleList_Next(CircleList* list) // O(1)
{
    TCircleList* sList = (TCircleList*)list;
    CircleListNode* ret = NULL;

    if( (sList != NULL) && (sList->slider != NULL) )
    {
        ret = sList->slider;
        sList->slider = ret->next;
    }

    return ret;
}


双向链表的不同之处
1、插入

指针分为两个next、pre
这里写图片描述

//第一个值的注意的:当链表插入第一个元素
if(next != NULL)
    next->pre = node;
node->pre = current;
//第二个值的注意的:当在0号位置插入
if(current == 新建节点)
    node->pre = NULL;

2、删除
这里写图片描述

if(next != NULL)
{
    next->pre = current;
    if(current == 新节点)//若第0号位置 需特殊处理
    {
        next->pre = NULL;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值