单链表

线性表的链式表示

一:基本概念及定义

         在顺序表中,由于逻辑上相邻的元素,其物理位置也是相邻的,因此可以随机存取顺序表的任何一元素,但是插入与删除需要移动大量元素,存储分配必须事先进行分配,事先分配的存储单元大小可能不适合问题的需要。链式的线性表可以解决上述顺序表的缺点。

 

定义:线性表的链式存储是采用一组任意的存储单元存放线性表的元素,这些存储单元可以是连续的,也可以是不连续的。为了表示每个元素与其直接后继元素的逻辑关系,除了需要存储元素的信息外,还需要存储其后继元素的地址信息。这两部分组成的存储结构,称为结点。结点包括两个域:数据域和指针域。其中数据域存放数据元素的信息,指针域存放元素后继的存储地址。如下图所示。

        链式的存取必须从头指针head开始,头指针指向链式的第一个结点,不过有时为了操作方便,会在第一个结点之前增加一个头结点(不过不是必要的),头结点的数据域可以存放线性表的长度等。最后一个结点的指针域为“NULL”。

单链表的存储结构用C语言来描述如下:

typedef struct Node
{
	DataType data;
	Struct Node *next;
}ListNode,*LinkList;

其中,ListNode是链表的结点类型,LinkList是指向链表结点的指针类型。

LinkList L;则定义一个链表,L指向该链表的第一个结点,对于不带头结点的空链表来说,L= NULL;


二:单链表的基本运算

(1):单链表的初始化操作

//将单链表初始化为空,动态生成一个头结点,并将头结点的指针域置为NULL
void InitList(LinkList *head)
{
	if((*head=(LinkList)malloc(sizeof(ListNode)))==NULL)	//为头结点分配一个存储空间
		exit(-1);
	(*head)->next = NULL;			     //将单链表的头结点指针域为空
}
(2):判断单链表是否为空

//判断单链表是否为空,是的时候返回1,否则返回0
int ListEmpty(LinkList head)
{
	if(head->next == NULL)				//判断单链表头结点的指针域是否为空
		return 1;				//单链表为空的时候,返回,否则返回0
	else 
		return 0;
}
(3):按序号查找操作

/查找单链表中第i个结点,查找成功返回该结点的指针,否则返回NULL表示失败
ListNode *Get(LinkList head,int i)
{
	ListNode *p;
	int j;
	if(ListEmpty(head))				//判断是否为空
		return NULL;
	if(i < 1)
		return NULL;				//判断i是否合法
	j=0;
		p = head;
		while(p->next != NULL && j<i)
		{
			p = p->next;
			j++;
		}
		if(j == i)
			return p;				//找到第i个结点,返回指正p
		else 
			return NULL;			//没有找到第i个结点,返回NULL
}


(4):按内容查找操作

//查找线性表中元素值为e的元素,查找成功将对应元素的结点指针返回,否则返回NULL表示失败。
ListNode *LocateElem(LinkList head,DataType e)   
{
	ListNode *p;
	p = head->next;					//指针p指向第一个结点
	while(p)
	{
		if(p->data == e)				//找到与e相等的元素,返回该序号
		{
			return p;
			break;
		}		
		else 
			p = p->next;
	}
	if(p == NULL)			//如果没有找到与e相等的元素,返回NULL
		return NULL;

}

(5):定位操作

//查找线性表中元素值为e的元素,查找成功将对应元素的序号返回,否则返回0表示失败。
int LocatePos(LinkList head,DataType e)   
{	
	ListNode *p;
	int i;
	if(ListEmpty(head))				//在查找第i个元素之前,判断链表是否为空
			return 0;
		p = head->next;					//指针p指向第一个结点
		i = 1;
		while(p)
		{
			if(p->data == e)				//找到与e相等的元素,返回该序号
				return i;		
			else 
			{
				p = p->next;
				i++;
			}

		}
		if(!p)			//如果没有找到与e相等的元素,返回0
			return 0;	
}

(6):插入操作( 仅限在中间结点插入)

//第i个位置插入一个结点,结点的元素值为e。插入成功返回1,失败返回0
int InsertList(LinkList head, int i, DataType e)
{
	ListNode *p,*pre;			//定义指向第i个元素的前驱结点指针pre,指针p指向新生成的结点
	int j;
	pre = head;					//指针p指向头结点
	j = 0;
	while(pre->next != NULL && j<i-1)			//找到第i-1个结点,即第i个结点的前驱结点
	{
		pre = pre->next;
		j++;
	}
	if(j!= i-1)					//如果没找到,说明插入位置错误
	{
		printf("插入位置错");
		return 0;
	}
	//新生成一个结点,并将e赋值给该结点的数据域
	if((p = (ListNode*)malloc(sizeof(ListNode))) == NULL)
		exit(-1);
	p->data = e;
	p->next = pre->next;			//插入新结点
	pre->next = p;
	return 1;	
}


(7):删除操作(仅限在中间结点删除)          其余两种插入和删除见网址:http://blog.youkuaiyun.com/xubin341719/article/details/7091979

//删除单链表中的第i个位置的结点。删除成功返回1,失败返回0
int DeleteList(LinkList head,int i,DataType *e)
{
	ListNode *p,*pre;
	int j;
	pre = head;
	j =0;
	while(pre->next != NULL && pre->next->next != NULL && j<i-1)		//判断是否找到前驱结点
	{
		pre = pre->next;
		j++;
	}
	if(j!=i-1)				//如果没找到要删除的结点位置,说明删除位置错误
    {
        printf("删除位置错误");
        return 0;
	}
	else
		 p=pre->next;
		*e=p->data;
		//将前驱结点的指针域指向要删除结点的下一个结点,也就是将p指向的结点与单链表断开
		pre->next=p->next;
		free(p);				//释放p指向的结点
		return 1;
}

(8):求表长操作

//计算链表的长度
int ListLength(LinkList head)
{
    ListNode *p;
    int count;
	count = 0;
    p=head;
    while(p->next !=NULL)
    {
        p=p->next;
        count++;
    }
    return count;
}

(9):摧毁链表操作

//清空单链表
void DestroyList(LinkList head)
{
    ListNode *p,*q;
    p=head;
    while(p!=NULL)
	{
		q=p;
        p=p->next;
        free(q);
    }
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值