数据结构学习入门

来源:互联网 发布:网络作家收入 编辑:程序博客网 时间:2024/06/03 11:22

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;    }}
原创粉丝点击