Linux-C学习笔记--单链表的“浮云”操作

14 篇文章 0 订阅
12 篇文章 0 订阅

链表在C语言项目中很常见,学号链表,先从单链表开始,通常在学习阶段的单链表实现是基于某种数据类型或结构量身定做的操作方法,这种方法,没有通用性,在实际项目开发中,段不可取。于是乎,学习一种“浮云”般对单链表的操作是非常重要的。我们研究各个数据结点的数据,就会发现,无论它是什么类型,都有一个共同的特点,就是,他们都是存储在内存中的,它们拥有各子唯一的内存地址,于是乎,我们使用单链表的每个结点存储目标数据的地址,就可以抽象出一种通用的单链表操作方法,具体的操作方法,如下,此代码支持任何数据类型的单链表操作:

/**********************************************************************************************/

file : LinkList.h

#ifndef _LINKLIST_H_
#define _LINKLIST_H_

typedef void LinkList;
typedef void LinkListNode;

extern LinkList* LinkList_Create();

extern void LinkList_Destroy(LinkList* list);

extern void LinkList_Clear(LinkList* list);

extern int LinkList_Length(LinkList* list);

extern int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);

extern LinkListNode* LinkList_Get(LinkList* list, int pos);

extern LinkListNode* LinkList_Delete(LinkList* list, int pos);

extern void LinkList_Reverse(LinkList* list);

#endif



/*******************************************************************************************************/

file : LinkList.c

#include <stdio.h>
#include <malloc.h>
#include "LinkList.h"


typedef struct _tag_TLinkListNode TLinkListNode;
struct _tag_TLinkListNode
{
	unsigned int addr;
    TLinkListNode* next;
};


typedef struct _tag_TLinkList
{
	int length;
	TLinkListNode* header;
}TLinkList;


LinkList* LinkList_Create()
{
	TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList));
	
	if(ret != NULL)
	{
		ret->length = 0;
		ret->header = NULL;
	}
	
	return (LinkList*)ret;
}


void LinkList_Destroy(LinkList* list)
{
	LinkList_Clear(list);
	free(list);
	list = NULL;
}


void LinkList_Clear(LinkList* list)
{
	TLinkList* sList = (TLinkList*)list;
	
	if(sList != NULL)
	{
		while(sList->header != NULL)
		{
			TLinkListNode* pList = sList->header;
			sList->header = pList->next;
			free(pList);
			sList->length--;
		}
	}
}


/************************************************************************
* 获取单链表长度
* 返回-1表示获取失败
* 返回非负数既是单链表当前长度
************************************************************************/
int LinkList_Length(LinkList* list)
{
	int ret = -1;
	TLinkList* sList = (TLinkList*)list;
	
	if(sList != NULL)
	{
		ret = sList->length;
	}
	
	return ret;
}


/************************************************************************
* 插入结点
* 插入成功返回真
* 插入失败返回假 
************************************************************************/
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
{
	int i = 0;
	TLinkList* sList = (TLinkList*)list;
	int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
	
	if(ret)
	{
		TLinkListNode* pNew = (TLinkListNode*)malloc(sizeof(TLinkListNode));
		if(pNew != NULL)
		{
			pNew->addr = (unsigned int)node;


			if(pos == 0 || sList->header == NULL)
			{
				pNew->next = sList->header;
				sList->header = pNew;
			}
			else
			{
				TLinkListNode* current = sList->header;
		
				for(i = 1; (i < pos) && (current->next != NULL); i++)
				{
					current = current->next;
				}
		
				pNew->next = current->next;
				current->next = pNew;
			}
			sList->length++;
		}
		else
		{
			ret = 0;
		}
	}
	
	return ret;
}

/************************************************************************
* 获取pos位置的结点
* 成功返回结点指针
* 失败返回空 
************************************************************************/
LinkListNode* LinkList_Get(LinkList* list, int pos)
{
    int i = 0;
	TLinkList* sList = (TLinkList*)list;
    LinkListNode* ret = NULL;
    
    if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
    {
        if(0 == pos)
		{
			ret = (LinkListNode*)(sList->header->addr);
		}
		else
		{
			TLinkListNode* current = sList->header;
		    for(i=1; i<pos; i++)
		    {
		        current = current->next;
		    }
			ret = (LinkListNode*)(current->next->addr);
		}
    }
    
    return ret;
}

/************************************************************************
* 删除pos位置的结点,并将删除的结点指针返回
* 成功返回结点指针
* 失败返回空 
************************************************************************/
LinkListNode* LinkList_Delete(LinkList* list, int pos)
{
    TLinkList* sList = (TLinkList*)list;
    LinkListNode* ret = NULL;
    int i = 0;
    
    if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
    {
		TLinkListNode* current = sList->header;
        if(0 == pos)
		{
			ret = (LinkListNode*)(sList->header->addr);
			sList->header = current->next;
			free(current);
		}
		else
		{
		    for(i=0; i<pos-1; i++)
		    {
		        current = current->next;
		    }
			ret = (LinkListNode*)(current->next->addr);
			current->next = current->next->next;
			free(current->next);
		}
		
		sList->length--;
    }
    
    return ret;
}

/************************************************************************
* 两种单链表逆序的操作
* 无返回值
************************************************************************/
#if 1
/************************************************************************
// 修改结点指针
void LinkList_Reverse(LinkList* list)
{
	TLinkList* sList = (TLinkList*)list;
	TLinkListNode* p1 = sList->header;


	if(LinkList_Length(list) == 2)
	{
		sList->header = p1->next;
		sList->header->next = p1;
		p1->next = NULL;
	}
	else if(LinkList_Length(list) > 2)
	{
		TLinkListNode* p2 = p1->next;
		sList->header = p2->next;
		p1->next = NULL;


		while(sList->header != NULL)
		{
			p2->next = p1;
			p1 = p2;
			p2 = sList->header;
			sList->header = sList->header->next;
		}
		sList->header = p2;
		p2->next = p1;
	}
}
#else
// 利用单链表删除、插入操作,将原有单链表第0个数据结点取出来,存入临时单链表中的第0个数据
// 结点位置,直到原有单链表为空,再将临时单链表还给原有链表指针
void LinkList_Reverse(LinkList* list)
{
	if(LinkList_Length(list) >= 2)
	{
		TLinkList* sList = (TLinkList*)list;
		LinkList* swapList = LinkList_Create();
		while(sList->header != NULL)
		{
			LinkList_Insert(swapList, LinkList_Delete(list, 0), 0);
		}


		sList->header = ((TLinkList*)swapList)->header;
		sList->length = ((TLinkList*)swapList)->length;
		((TLinkList*)swapList)->header = NULL;
		((TLinkList*)swapList)->length = 0;
		LinkList_Destroy(swapList);
	}
}
#endif


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值