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;
}
}