数据结构学习入门
来源:互联网 发布:网络作家收入 编辑:程序博客网 时间: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; }}
阅读全文
0 0
- 数据结构入门学习中。。。
- 数据结构学习入门
- 数据结构入门学习系列-1(基本数据结构)
- 数据结构学习(一):入门
- JSON入门级学习小结--JSON数据结构
- JSON入门级学习小结--JSON数据结构
- 《数据结构与算法》学习之入门篇
- 数据结构与算法学习-哈希表入门
- 数据结构入门到精通学习(一)
- 数据结构入门学习系列-10(霍夫曼树)
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 数据结构入门
- 【算法零基础入门】 学习笔记一 什么是数据结构
- js判断是否为IE678简易办法
- 微信小程序——1、搭建自己的Https服务器
- 4轴开发之串级PID调试技巧
- STM32 USART串口初始化
- 最新闻:陨石落云南,震感强烈
- 数据结构学习入门
- C++的引用【转自fenghuan】
- ubuntu17.10 网易云音乐无法启动
- U3D粒子系统
- 博客
- 枚举类
- Xshell链接错误:Could notconnect to '192.168.18.128' (port 22): Connection failed.
- U3D后期全屏幕渲染特效
- Hadoop源码解析之: TextInputFormat如何处理跨split的行