不带头结点的链表操作及其逆置

一、概述

前面我们已经完成了带头结点的链表,今天我们来完成一下不带头结点的链表。事实上不带头结点的链表玉带头结点的链表差别在哪呢?
(1)带头结点的单链表更容易操作,因为不带头结点的单链表在第一个节点的操作与其他节点不一样,在初始化的时候就必须把第一个结点创建出来,然后将它的next置空而不带头结点的单链表则直接置空即可。
(2)不带头结点的单链表,初始化时一定要返回指向头结点的地址,所以要用二级指针。
(3) 不带头结点的单链表在插入、删除、输出时判断条件不一样,不带头结点的单链表判断为空时是while(head!=NULL)而不是while(head->next!=NULL)。

为什么不带头结点初始化有2种方式,而带头结点只有1种方式呢?

     因为不带头结点声明Node *head 时;C编译器将其自动初始化为NULL,于是根本不需要调用InitList(head);也即不带头结点的初始化是个伪操作。而带头结点的初始化在堆开辟了一段内存,需要修改head指针变量指向的地址(即head的值),所以要修改head的值,必须传保存head变量的地址(即二维指针)。

二、代码实现

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int Elemtype;
typedef struct Node
{
	Elemtype data;
	Node* next;
}Node,*plist;
void Initlist(plist *head)
{
	(*head) = (plist)malloc(sizeof(Node));
	if(NULL == head)exit(0);
	(*head)->next = NULL;
}
bool Insert_head(plist head,Elemtype val)
{
	bool rt = false;
	plist After = head-> next;
	plist NewNode = (plist)malloc(sizeof(Node));
	if(NewNode == NULL)exit(0);
	head->next = NewNode;
	NewNode->next = After;
	NewNode->data = val;
	rt = true;
	return rt;
}
bool Insert_tail(plist head,Elemtype val)
{
	bool rt = false;
	plist After = head;
	for(;After->next != NULL;After = After->next);
	plist NewNode = (plist)malloc(sizeof(Node));
	if(NewNode == NULL)exit(0);
	NewNode->next = NULL;
	After->next = NewNode;
	NewNode->data = val;
	rt = true;
	return rt;
}
plist Search_Node(plist head,Elemtype val)
{
	plist pre = head;
	for(;pre->next!=NULL;pre = pre->next)
	{
		if(pre->next->data == val)
		{
			return pre;
		}
		
	}
	return NULL;
}
bool Dele_Node(plist head,Elemtype val)
{
	bool rt = false;
	plist pre = Search_Node(head,val);
	if(pre != NULL)
	{
		plist pAfter = pre->next;
	    pre->next = pAfter->next;
	    free(pAfter);
	    rt  = true;
	}

	return rt;
}
int Getlength(plist head)
{
	int count = 0;
	plist pCur = head;
	while(pCur!= NULL)
	{
		count++;
		pCur = pCur ->next;
	}
	return count;
}
void Clear(plist head)
{
	plist pCuer = head->next;
	plist pAfter = pCuer;
	while(pCuer)
	{
		pAfter = pCuer->next;
		free(pCuer);
		pCuer = pAfter;
	}
	head->next = NULL;
}
void Destory(plist head)
{
	Clear(head);
	free(head);
	head = NULL;
	
}
void Reverse(plist head)//逆置链表初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。
{
	bool rt = false;
	plist pCur = head->next;
	head->next = NULL;
	plist pAfter = pCur;
	while(pCur)
	{
		pAfter = pCur->next;
		pCur->next = head->next;
		head->next = pCur;
		pCur = pAfter;
	}
}
void Show(plist head)
{
	plist pre = head->next;
	while(pre)
	{
		printf("%d ",pre->data);
		pre = pre->next; 
	}
	printf("\n");
}


猜你喜欢

转载自blog.csdn.net/lixin_com/article/details/78115787