链表之单链表

 

一、什么是链表,链表的分类?

·链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

·八种链表结构:

1,单向、双向

2,带头、不带头

3,循环、非循环

常用的有: 1,无头单向非循环链:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构

链表之单链表

                   2,带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。链表之单链表

二、链表带头结点和不带头结点的区别?

所有的链表都有一个头指针head,带头结点的链表中head的数据项为空,而不带头的链表直接在头结点存入数据,那么当从头插入数据时,head需要时刻变化。带头结点的单链表,不论删除和插入的位置如何,不需要修改head的值,不带头结点的单链表当头插和头删需要修改head的值。所以一般单链表一般带有头结点。

三、单链表的以下基本操作:

 

typedef int SDataType; 

// 链表的节点 
typedef struct SListNode 
{ 
SDataType _data; 
struct SListNode* _pNext; 
}Node, *PNode; 


// 链表的结构,给一个头指针保存链表第一个节点的地址 
typedef struct SList 
{ 
PNode _pHead; // 指向链表中的第一个节点 
}SList, *PSList; 


// 链表的初始化 
void SListInit(SList* s); 
{
  assert(s);
  s->_Phead = NULL;
}
PNode BuySListNode(SDataType data)
{
	PNode pNewNode = (PNode)malloc(sizeof(Node));
	if (NULL == pNewNode)
	{
		assert(0);
		return NULL;
	}

	pNewNode->_data = data;
	pNewNode->_pNext = NULL;
	return pNewNode;
}
// 在链表s最后一个节点后插入值为data的节点 
void SListPushBack(SList* s, SDataType data); 
{
  assert(s);
  PNode pNewNode = BuySListNode(data);
  if (NULL == s->_pHead)
{
  //空链表
  s->_pHead = pNewNode;  
}
 else
 {
 //链表非空,找链表最后一个节点
 PNode pCur = s->_pHead;
 while(pCur->_pNext)
   pCur = pCur->_pNext;
   pCur->_pNext = pNewNode; 
 }
}
// 删除链表s最后一个节点 
void SListPopBack(SList* s); 
  assert(s);
  if(NULL == s->_pHead) //空链表
   return;
  else if (NULL == s->_pHead->_pNext)  // 只有一个节点
 {
   free(s->_pHead);
   s->_pHead = NULL;
 }
  else
 {
    //多个节点
   PNode pPre = NULL;
   PNode pCur = s-_pHead;
   while(pCur->_pNext)
  {
    pPre = pCur;
    pCur = pCur->pNext;
  }
    free(pCur);
    pPre->_pNext = NULL;
 } 
}
// 在链表s第一个节点前插入值为data的节点 
void SListPushFront(SList* s, SDataType data); 
{
  assert(s);
  PNode pNewNode = BuySListNode(data);
  pNewNode->_pNext = s->_pHead;
  s->_pHead = pNewNode;
}
// 删除链表s的第一个节点 
void SListPopFront(SList* s); 
{
  PNode pDelNode = NULL;
  assert(s);
  if(NULL == s->_pHead)
    return;
 //找到待删除的节点
  pDelNode = s->_pHead;
  s->_pHead = pDelNode->_pNext;
  free(pDelNode);
}
// 在链表的pos位置后插入值为data的节点 
void SListInsert(PNode pos, SDataType data); 
{
  PNode pNewNode = NULL;
  if(NULL == pos)
   return;
  pNewNode = BuySListNode(data);
  pNewNode->_pNext = pos->_pNext;
  pos->_pNext = pNewNode;
}
// 删除链表s中pos位置的节点 
void SListErase(SList* s, PNode pos); 
{
   assert(s);
   if(NULL == pos || NULL == s->_pHead)
   return;
  if(pos == s->_pHead)
{
  s->_pHead = pos->_pNext;
}
 else
{
  PNode pPrePos = s->_pHead;
  while(pPrePos && pPrePos->_pNext != pos)
     pPrePos = pPrePos->_pNext;
  if(pPrePos)
   pPrePos->_pNext = pos->_pNext;
}
  free(pos);
}
// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL 
PNode SListFind(SList* s, SDataType data); 
{
  assert(s);
  PNode pCur = s->_pHead;
  while(pCur)
 {
  if(pCur->_data == data)
    return pCur;
    pCur = pCur->_pNext;
 }
    return NULL;
}
// 获取链表中有效节点的个数 
size_t SListSize(SList* s); 
{
  assert(s);
  PNode pCur = s->_pHead;
  size_t count = 0;
  while(pCur)
 {
   count++;
   pCur = pCur->_pNext;
 }
   return conut;
}
// 检测链表是否为空 
int SListEmpty(SList* s); 
{
   assert(s);
   return NULL == s->_pHead;
}
// 将链表中有效节点清空 
void SListClear(SList* s); 
{
   assert(s);
   if(NULL == s->_pHead)
    return;
  PNode pPre = NULL;
  PNode pCur = s->_pHead;
  while(pCur)
 {
  if (pCur->_data == data)
{
if (pCur == s->_pHead)
{
	s->_pHead = pCur->_pNext;
}
else
{
	pPre->_pNext = pCur->_pNext;
}

	free(pCur);
	return;
 }
else
{
	pPre = pCur;
	pCur = pCur->_pNext;
}
			
}
}
// 销毁链表 
void SListDestroy(SList* s); 
{
 if(pCur->NULL)
{
 free(pCur);
}
}

 

上一篇:链表的增删改查排序删除等操作自实现


下一篇:链表中环的入口节点-剑指offer(Java实现)