单链表的基本操作

2.3.1单链表的定义

线性表的链式存储又称单链表,它是通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。
引入头结点的优点:
1、由于第一个数据结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作和在表的其他位置上的操作一致,无须进行特殊处理
2、无论链表是否为空,其头指针都指向头结点的非空指针(空表中头节点的指针域为空),因此空表和非空表的处理得到了统一

typedef struct LNode{//定义单链表结点类型 
	ELemType data;//数据域 
	struct LNode *next;//指针域 
}LNode,*LinkList;

2.3.2单链表上基本操作的实现

1、链表的建立

1、带头结点的头插法

LinkList List_Head(LinkList &L)//逆向建立单链表 
{
	LNode *s,x;
	L=(LinkList)malloc(sizeof(LNode));//创建头结点 
	L->next=NULL;//初始化空链表 
	scanf("%d",&x);//输入节点的值 
	while(x!=9999){//输入9999表示结束 
		s=(LNode*)malloc(sizeof(LNode));//创建新结点 
		s->data=x;
		s->next=L->next;
		L->next=s;//将新结点插入表中,L为头指针 
		scanf("%d",&x);
	}
	return L;
} 

2、不带头结点的头插法

void InsertByHead(pNode *pHead, int value)
{
    pNode pNew = (pNode)malloc(sizeof(Node));
    if (NULL == pNew)
    {
        printf("malloc free failed!\n ");
        return;
    }
    pNew->value = value;
    pNew->next = *pHead;
    *pHead = pNew;
}

3、带头结点的尾插法

LinkList List_TailInsert(LinkList &L)
{
	InitList(L);
	LNode *s,*r=L;
	ElemType e;
	printf("输入元素(输入9999为停止)");
	scanf("%d",&e);
	while(e!=9999)
	{
		s=(LNode*)malloc(sizeof(LNode));
		s->data=e;
		r->next=s;
		r=s;
		scanf("%d",&e);
	 }
	r->next=NULL;
	return L; 
}

4、不带头结点的尾插法

void InsertByTail(pNode *pHead, int value)
{
    if (NULL ==*pHead)
    {
        InsertByHead(pHead, value);

    }
    else
    {
        pNode pNew = (pNode)malloc(sizeof(Node));
        if (NULL == pNew)
        {
            printf("malloc free failed!\n ");
            return;
        }
        pNew->value = value;
        pNew->next = NULL;
        pNode pos = *pHead;
        while (pos->next != NULL)
        {
            pos = pos->next;
        }
        pos->next = pNew;


    }
}

5、按序号查找结点值

LNode *GetElem(LinkList L,int i)
{
	int j=1;
	LNode *p=L->next;
	if(i==0)
		return L;
	if(i<1)
		return NULL;
	while(p&&j<i){
		p=p->next;
		j++;
	}
	return p;
}

6、按值查找表结点

LNode *LocateElem(LinkList L,ElemType e){
	LNode *p=L->next;
	while(p!=NULL&&p->data!=e)
		p=p->next;
	return p;
}

7、插入节点操作

向某一结点后插入

p=GetElem(L,i-1);
s->next=p->next;
p->next=s;

向某一结点前插入

 方法1
s->next=p->next;//修改指针域,不能颠倒 
p->next=s;
temp=p->data;//交换数据域 
p->data=s->data;
s->data=temp;


方法2
Q=P;
P=L;
while(P->next!=Q) P=P->next;
S->next=P->next;
P->next=S; 

8、删除节点操作

带头节点

p=GetElem(L,i-1);//查找删除位置的前驱结点 
q=p->next;//令q指向被删除结点 
p->next=q->next;//将*q结点从链中"断开" 
free(q);//释放结点的存储空间 

不带头结点

//头删
void DeleteByHead(pNode *pHead)
{
    if (*pHead != NULL)
    {
        pNode pos = *pHead;
        *pHead = pos->next;
        free(pos);
        pos = NULL;
    }
}
//尾删
void DeleteByTail(pNode *pHead)
{
    if (NULL ==(*pHead)->next  || NULL == *pHead)
    {
        DeleteByHead(pHead);

    }
    else
    {
        pNode pos = *pHead;
        while (pos->next->next != NULL)
        {
            pos = pos->next;
        }
        free(pos->next);
        pos->next = NULL;
    }
}

9、表长

不带头结点求表长

int GetLength(pNode pHead)
{
	pNode pos=pHead;
	int count=0;
	while(pos!=NULL)
	{
		pos=pos->next;
		count++;
	}
	return count;
 } 

带头节点的

//得到带头结点的单链表表长
int Length(LinkList L)
{
	int length = 0;
	while(L->next != NULL)
	{
		length++;
		L = L->next;
	}
	return length;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值