单链表基本操作以及一些常见的面试问题


/*  线性表的链式存储结构 */

typedef int ElemType;
typedef int Status;
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;


/* 将单链表初始化为空, 动态生成一个头结点, 并将头结点的指针域置为空 */

Status LinkListInit(LinkList *L)
{
    (*L) = (LinkList)malloc(sizeof(struct LNode));
    if(*L == NULL)
        return -1;
    (*L)->next = NULL;

    return 0;
}

/* 销毁线性表 */
void LinkListDestroy(LinkList *L)
{
    LinkList q;
    while(*L)  /* 头结点也要释放掉 */
    {
        q = (*L)->next;
        free(*L);
        (*L) = q;
    }
}

/* 将L重置为空表 */

void LinkListClear(LinkList L)
{
    LinkList p, q;
    p = L->next; /* 第一个结点*/
    while(p)
    {
        q = p->next;
        free(p);
        p = q;
    }
    L->next = NULL;
}

/* 判断单链表是否为空 */

Status LinkListEmpty(LinkList L)
{
    return (L->next == NULL);
}

/* 返回L的长度 */

int LinkListLength(LinkList L)
{
    int i = 0;
    LinkList p;
    p = L->next; /* 指向第一个结点 */
    while(p)
    {
        i++;
        p = p->next;
    }
    return i;
}


/* 当第i个元素存在时,其值赋给e */

Status LinkListGetElem(LinkList L, int i, ElemType *data)
{
    int j = 1;
    LinkList p;
    p = L->next;
    while(p != NULL && j < i) /* 从第1个结点开始,滑动i-1步到达第i个结点(1<=i<= Len) */
    {
        p = p->next;
        j++;
    }
    if(p == NULL || j > i)
    {
        return -1;
    }
    *data = p->data;
}

/* 返回L中第1个与e满足关系compare()的数据元素的位序  */

int LinkListLocateElem(LinkList L, ElemType e, Status (*compare)(ElemType, Elemtype))
{
    int i = 0;
    LinkList p = L->next;
    while(p)
    {
        i++;
        if(compare(p->data, e))
            return i;
        p = p->next;
    }
    return 0;
}

/* 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱 */

Status LinkListPriorElem(LinkList L, ElemType cur, ElemTpye *pre)
{
    LinkList p, q;
    p = L->next; /* 第一个结点 */
    while(p->next) /* 有至少两个或以上的结点 */
    {
        q = p->next; /* q是p的后继 */
        if(q->data == cur)
        {
            *pre = p->data; /* 前驱 */
            return 0;
        }
        p = q;
    }
    return -1;
}

/* 若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继 */

Status LinkListNextElem(LinkList L, ElemType cur, ElemType *next)
{
    LinkList p = L->next; /* 第一个结点 */
    while(p->next) /* 当前结点有后继 */
    {
        if(p->data == cur)
        {
            *next = p->next->data;
            return 0;
        }
        p = p->next;
    }
    return -1;
}

/* 在带头结点的单链线性表L中第i(1<=i<=len)个位置之前插入元素e */

Status LinkListInsert(LinkList L, int i, ElemType e)
{
    int j;
    LinkList p, s;
    p = L; /* 指向头结点*/
    j = 1;
    while(p && j < i) /* 滑动到第i个结点的前一个结点处 */
    {
         j++;
         p = p->next;
    }
    if(p == NULL || j > i)
    {
        return -1;
    }
    s = (LinkList)malloc(sizeof(struct LNode));
    if(s == NULL)
    {
         return -1;
    }
    s->data = e;
    s->next = p->next;
    p->next = s;
    return 0;
}

/*  在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */

Status LinkListDelete(LinkList L, int i, ElemType *e)
{
    int j = 1;
    LinkList p, q;
    p = L; /* 指向头结点 */
    while(p->next && j < i) /* */
    {
        p = p->next;
        j++;
    }
    if(p->next == NULL || j > i)
    {
        return -1;
    }
    q = p->next;
    p->next = q->next;
    *e = q->data;
    free(q);
    return 0;
}

/* 依次对L的每个数据元素调用函数vi()  */

void LinkListTraverse(LinkList L, void (*vi)(ElemType))
{
    LinkList p = L->next;
    while(p)
    {
        vi(p->data);
        p = p->next;
    }
}


/* 单链表反转/逆序 */

Status LinkListReverse(LinkList L)
{
    LinkList current, prev, pnext;
    current = L->next;
    pnext = current->next;
    current->next = NULL;
    while(pnext)
    {
        prev = pnext->next;
        pnext->next = current;
        current = pnext;
        pnext = prev;
    }
    L->next = current;
    return 0;
}

/* 单链表反转/逆序的另一个方法*/

Status LinkListRevers2(LinkList L)
{
	LinkList current, p;
	if(L == NULL) /*  空表返回 */
	{
		return ;
	}
	current = L->next; /* 第1个元素节点处 */
	while(current->next != NULL)
	{
		p = current->next; /* p为要被提取出来的节点 */
		current->next = p->next; /* 断开要被提取出来的节点 */
		p->next = L->next; /* 被提取出来的结点插入到首元结点前面 */
		L->next = p; /* 被提取出来的节点成为首元结点 */
	}

	return ;
}


/* 倒数第n个元素 */

Status LinkListGetNthNodeFromBack(LinkList L, int n, ElemType *e)
{
	int i = 0;
	LinkList firstNode, secNode;
	firstNode = L;
	secNode = L;
	while(i < n && firstNode->next != NULL)
	{
		/* 正数n个节点,firstNode指向正的第n个节点 */
		i++;
		firstNode = firstNode->next;
	}
	if(firstNode->next == NULL && i < n - 1)
	{
		/* 节点数量少于n个 */
		return -1;
	}

	while(firstNode != NULL)
	{
		secNode = secNode->next;
		firstNode = firstNode->next;
	}

	*e = secNode->data;

	return 0;
}

/* 获取中间结点 */

Status LinkListGetMidNode(LinkList L, ElemType *e)
{
	LinkList search, mid;
	mid = search = L;
	while(search->next != NULL)
	{
		if(search->next->next != NULL)
		{
			search = search->next->next;
			mid = mid->next;
		}
		else
		{
			search = search->next;
		}
	}

	*e = mid->data;

	return 0;
}

/* 判断是否有环 */

int LinkListHasLoop(LinkList L)
{
	LinkList p, q;

	p = q = L;

	while(p != NULL && q != NULL && q->next != NULL)
	{
		p = p->next;
		if(q->next != NULL)
			q = q->next->next;

		if(p == q)
			return 1;
	}

	return 0;
}

/* 判断是否有环的另外一个方法 */

int LinkListHasLoop2(LinkList L)
{
	LinkList p, q;
	int pos1, pos2;

	p = q = L;
	pos1 = 0;
	while(p)
	{
		q = L;
		pos2 = 0;
		pos1++;
		while(q)
		{
			pos2++;
			if(p == q)
			{
				if(pos1 == pos2)
					break;
				else
					return 1;
			}
			q = q->next;
		}
		p = p->next;
	}
}

/* 单链表建环, num:环入口的节点 */
Status LinkListBulidLoop(LinkList *L, int num)
{
	int i = 0;
	LinkList cur = *L;
	LinkList tail = NULL;

	if(num <= 0 || L == NULL)
	{
		return -1;
	}
	for(i = 0; i < num; i++) /* 找到入口节点位置 */
	{
		if(cur == NULL)
		{
			return -1;
		}
		cur = cur->next;
	}
	tail = cur;
	while(tail->next)
	{
		tail = tail->next;
	}
	tail->next = cur;

	return 0;
}

/* 删除重复元素 */

LinkList LinkListRemoveDupNode(LinkList L)
{
	LinkList p, q, r;

	p = L->next; /* 第一个元素节点 */
	while(p)
	{
		q = p;
		while(q->next)
		{
			if(q->next->data == p->data)
			{
				r = q->next;
				q->next = r->next;
				free(r);
			}
			else
			{
				q = q->next;
			}
		}
		p = p->next;
	}

	return L;
}






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值