数据结构----单链表的创建、插入、删除、读取、遍历

阅读《大话数据结构》关于链表的章节后,自己尝试写出了链表的几个函数,在微博进行记录。

代码如下:

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

//创建链表结构体
typedef struct Node
{
	int data;
	struct Node *next;
}Node;
typedef  Node* LinkList;  //定义LinkList的数据类型为Node*



//尾插法创建链表,表头后有n个结点
void CreateListHead(LinkList *L,int n)
{
	int i;
	LinkList p, q;

	*L = (LinkList)malloc(sizeof(Node));  //申请头结点的内存空间

	p = *L;
	p->data = n;	//头结点数据域,存储链表的数据的长度

	for (i = 0; i < n; i++)
	{
		q = (LinkList)malloc(sizeof(Node)); 
		q->data = i+1; //给新建的结点的数据域赋值
		p->next = q;   //末尾结点的指针域指向新创建的结点
		p = q;         //p指针缓存q的地址,下一循环中p->next,即为q->next,使本循环中q的指针域指向下一结点
	}
	p->next = NULL;    //尾结点指针域为空
}

//获取链表中第i个结点的数据并返回给e,i为0取的是头结点数据域(除头结点外,结点的个数)
int GetElem(LinkList L,int i,int* e)
{
	LinkList p;

	p = L;

	while(p && i--)   //找到第i个结点
	{
		p = p->next;
	}

	if(!p) return 0;  //第i个结点为空,报错

	*e = p->data;     //将第i个结点的数据赋值给*e
	 
	return !0;
}


//在链表头结点后第i个结点位置插入一个节点,数据域为e,原结点后移
int ListInsert(LinkList *L,int i,int e)
{
	LinkList p,q;

	if ( i < 1) return 0;    //i为0,报错

	q = *L;

	while (q && --i)     //寻找第i-1个结点的位置
	{
		q = q->next;
	}

	if (!q) return 0;    //i-1结点为空,报错

	p = (LinkList)malloc(sizeof(Node));  //p申请内存空间,应在找到i-1结点后申请,否则可能因报错浪费内存空间

	p->next = q->next;   //新建结点的指针域 = i-1位置结点的指针域
	q->next = p;         //i-1位置结点的指针域指向新建的结点
	p->data = e;         //新建结点的数据域为e

	(*L)->data++;        //链表长度+1

	return !0;
}

//删除链表头结点后第i个结点,并将该结点数据返回给*e
int ListDelete(LinkList *L,int i,int* e)
{
	LinkList p, q;

	if (i < 1) return 0;    //i为0,报错

	q = *L;

	while (q && --i)   //寻找第i-1结点
	{
		q = q->next;
	}

	if (!q->next) return 0;  //i-1结点指针域为空,即第i个结点不存在,报错

	p = q;
	p = p->next;       //p为第i个结点
	*e = p->data;      //将第i个结点的数据返回给*e
	q->next = p->next; //将i-1结点的指针域变为第i个结点的指针域

	free(p);           //释放第i结点的内存

	(*L)->data--;      //链表长度减一

	return !0;
}

//遍历链表数据(包括头结点)
void PrintfList(LinkList L)
{
	LinkList p;

	p = L;   //直接遍历链表L,会使L不再指向头结点
	while (p) //当L为NULL时,停止打印DATA
	{
		printf("%d\n", p->data);
		p = p->next;
	}
}


 main() 
{
	 int temp;
	 LinkList L;

	 CreateListHead(&L, 5);             //创建一个链表,头结点后有5个结点
	 printf("创建的链表为:\n");
	 PrintfList(L);


	 if (ListInsert(&L, 6, 100))        //在第6个结点位置插入数据为100的结点
	 {
		 printf("在第6个结点位置插入结点后链表为:\n");
		 PrintfList(L);
	 }
	 else
	 {
		 printf("在第6个结点位置插入结点失败\n");
	 }


	 if (ListDelete(&L, 1, &temp))   //删除头结点后第1个结点
	 {
		 printf("删除第1结点后链表为:\n");
		 PrintfList(L);
		 printf("删除的结点的数据为:%d\n", temp);
	 }	 
	 else
	 {
		 printf("删除第1结点失败\n");
	 }

	 if (GetElem(L, 4, &temp))       //读取头结点后第4个结点的数据
	 {
		 printf("读取头结点后第4个结点数据为:\n");
		 printf("%d\n", temp);
	 }
	 else
	 {
		 printf("读取头结点后第4个结点数据失败\n");
	 }
	 

	 getch(); //等待用户按键
}


编译的环境为VS2015,运行结果如下图:



这里需要注意的是,传递进函数里面的结构体指针变量,是传递它本身还是传递它的地址。

如:CreateListHead();函数,如果传递进去的不是&L而是L,是无法创建成功链表的。

具体参考:http://blog.csdn.net/a3748622/article/details/79286974


猜你喜欢

转载自blog.csdn.net/a3748622/article/details/79282326