作为想从事嵌入式方面的机械院学生,相比于搞计算机的,接触数据结构可能相对来说有点晚了,但我相信只要肯学习啥时都不算晚,博客就是督促我追赶上别人的最好见证。博客停更两天,第一天复习课程,昨天考试,当然,昨天也学习了,只是由于时间问题,加上调程序,没来得及更新博客,今天补上昨天的学习内容。接下来言归正传,首先来说下昨天的学习内容。
一 循环链表
在单链表中,可用于表示任意的线性关系,但是有些线性关系是循环的,即没有队尾元素(如生活中的月、周等),针对这些生活中的具体情况,为解决实际问题,我们引入循环链表。
循环链表的定义:将单链表中的最后一个数据元素的next指针指向第一个元素
当然,循环链表也拥有单链表的所有操作
循环链表之所以不同与单链表,是因为其引入了游标,可以完成一些新操作。
游标的定义:在循环链表中可以定义一个“当前”指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。
下边来说说循环链表的新操作:
获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list);
将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list);
将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list);
直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node);
下面为循环链表的各部分的实现代码:
#include <stdio.h>
#include <malloc.h>
#include "CircleList.h"
typedef struct _tag_CircleList
{
CircleListNode header;
CircleListNode* slider;
int length;
}TCircleList;
CircleList* CircleList_Create()
{
TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));
if(ret != NULL)
{
ret->length = 0;
ret->header.next = NULL;
ret->slider = NULL;
}
return ret;
}
void CircleList_Destroy(CircleList* list)
{
free(list);
}
void CircleList_Clear(CircleList* list)
{
TCircleList* slist = (TCircleList*)list;
if(slist != NULL)
{
slist->length = 0;
slist->header.next = NULL;
slist->slider = NULL;
}
}
int CircleList_Length(CircleList* list)
{
TCircleList* slist = (TCircleList*)list;
int ret = -1;
if(slist != NULL)
{
ret = slist->length;
}
return ret;
}
int CircleList_Insert(CircleList* list, CircleListNode* node, int pos)
{
TCircleList* slist = (TCircleList*)list;
int ret = (slist != NULL) && (pos >= 0) && (node != NULL);
int i = 0;
if(ret)
{
CircleListNode* current =(CircleListNode*)slist;
for(i = 0;(current->next != NULL) && (i < pos);i++)
{
current = current->next;
}
node->next = current->next;
current->next = node;
if(slist->length == 0)
{
slist->slider = node;
node->next = node;
}
slist->length++;
}
return ret;
}
CircleListNode* CircleList_Get(CircleList* list, int pos)
{
TCircleList* slist = (TCircleList*)list;
CircleListNode* ret = NULL;
int i = 0;
if((pos >= 0) && (slist != NULL))
{
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) )
{
CircleListNode* current = (CircleListNode*)slist;
CircleListNode* first = slist->header.next;
CircleListNode* last = (CircleListNode*)CircleList_Get(slist, slist->length - 1);
for(i=0; i<pos; i++)
{
current = current->next;
}
ret = current->next;
current->next = ret->next;
slist->length--;
if( first == ret )
{
slist->header.next = ret->next;
last->next = ret->next;
}
if( slist->slider == ret )
{
slist->slider = ret->next;
}
if( slist->length == 0 )
{
slist->header.next = NULL;
slist->slider = NULL;
}
}
return ret;
}
CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node)
{
TCircleList* slist = (TCircleList*)list;
CircleListNode* ret = NULL;
int i = 0;
if(slist != NULL)
{
CircleListNode* current = (CircleListNode*)slist;
for(i = 0;i < slist->length; i++)
{
if(current->next == node)
{
ret = current->next;
break;
}
current = current->next;
}
if(ret != NULL)
{
CircleList_Delete(slist,i);
}
}
return ret;
}
CircleListNode* CircleList_Reset(CircleList* list)
{
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)
{
TCircleList* slist = (TCircleList*)list;
CircleListNode* ret = NULL;
if(slist != NULL)
{
ret = slist->slider;
}
return ret;
}
CircleListNode* CircleList_Next(CircleList* list)
{
TCircleList* slist = (TCircleList*)list;
CircleListNode* ret = NULL;
if((slist != NULL) && (slist->slider != NULL))
{
ret = slist->slider;
slist->slider = ret->next;
}
return ret;
}
二、双向链表
同循环链表一样,双向链表也是针对于单项链表有些完不成的操作而进行的改进。
其中单链表的结点都有一个指向下一个结点的指针,单链表的数据元素无法直接访问其前驱元素,如果我们需要逆序访问单链表中的元素,那么使用单链表那就是极其耗时的操作,所以我们在此引入双向链表。
双向链表的定义:在单链表的结点中增加一个指向其前驱的pre指针
双向链表同样拥有单链表的所有操作,当然,同循环链表一样,双向链表也引入了一些新操作:
获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list);
将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list);
将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list);
将游标移动指向到链表中的上一个数据元素
CircleListNode* CircleList_Pre(CircleList* list);
直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node);
每部分的具体代码如下:
#include <stdio.h>
#include <malloc.h>
#include "DLinkList.h"
typedef struct _tag_DLinkList
{
DLinkListNode header;
DLinkListNode* slider;
int length;
}TDLinkList;
DLinkList* DLinkList_Create()
{
TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList));
if(ret != NULL)
{
ret->length = 0;
ret->header.next = NULL;
ret->header.pre = NULL;
ret->slider = NULL;
}
return ret;
}
void DLinkList_Destroy(DLinkList* list)
{
free(list);
}
void DLinkList_Clear(DLinkList* list)
{
TDLinkList* slist = (TDLinkList*)list;
if(slist != NULL)
{
slist->length = 0;
slist->header.next = NULL;
slist->header.pre = NULL;
slist->slider = NULL;
}
}
int DLinkList_Length(DLinkList* list)
{
TDLinkList* slist = (TDLinkList*)list;
int ret = -1;
if(slist != NULL)
{
ret = slist->length;
}
return ret;
}
int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
{
TDLinkList* slist = (TDLinkList*)list;
int ret = (slist != NULL) && (pos >= 0) && (node != NULL);
int i = 0;
if(ret)
{
DLinkListNode* current = (DLinkListNode*)slist;
DLinkListNode* next = NULL;
for(i = 0;(current->next != NULL) && (i < pos);i++)
{
current = current->next;
}
next = current->next;
current->next = node;
node->next = next;
if(next != NULL)
{
next->pre = node;
}
node->pre = current;
if( slist->length == 0)
{
node->pre = NULL;
slist->slider = node;
}
slist->length++;
}
return ret;
}
DLinkListNode* DLinkList_Get(DLinkList* list, int pos)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
int i = 0;
if((pos >= 0) && (pos <= slist->length) && (slist != NULL))
{
DLinkListNode* current = (DLinkListNode*)slist;
for(i=0;i<pos;i++)
{
current = current->next;
}
ret = current->next;
}
return ret;
}
DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
int i = 0;
if((pos >= 0) && (pos <= slist->length) && (slist != NULL))
{
DLinkListNode* current = (DLinkListNode*)slist;
DLinkListNode* next = NULL;
for( i=0;i<pos;i++ )
{
current = current->next;
}
ret = current->next;
next = ret->next;
current->next = next;
if( next != NULL )
{
next->pre = current;
if( current == (DLinkListNode*)slist )
{
next->pre = NULL;
}
}
if( slist->slider == ret )
{
slist->slider = next;
}
slist->length--;
}
return ret;
}
DLinkListNode* DLinkList_DeleteNode(DLinkList* list,DLinkListNode* node)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
int i = 0;
if(slist != NULL)
{
DLinkListNode* current = (DLinkListNode*)slist;
for( i=0; i<slist->length; i++)
{
if(current->next == node)
{
ret = current->next;
break;
}
current = current->next;
}
if(ret != NULL)
{
DLinkList_Delete(slist,i);
}
}
return ret;
}
DLinkListNode* DLinkList_Reset(DLinkList* list)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
if(slist != NULL)
{
slist->slider = slist->header.next;
ret = slist->slider;
}
return ret;
}
DLinkListNode* DLinkList_Current(DLinkList* list)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
if(slist != NULL)
{
ret = slist->slider;
}
return ret;
}
DLinkListNode* DLinkList_Next(DLinkList* list)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
if((slist != NULL) && (slist->slider != NULL))
{
ret = slist->slider;
slist->slider = ret->next;
}
return ret;
}
DLinkListNode* DLinkList_Pre(DLinkList* list)
{
TDLinkList* slist = (TDLinkList*)list;
DLinkListNode* ret = NULL;
if(slist != NULL)
{
ret = slist->slider;
slist->slider = ret->pre;
}
return ret;
}