单链表的基本实现

单链表是方向单一的链表,即就是只能从前向后访问,不能从后向前访问。这篇文章,我

将整理出单链表的一些基本功能。

1.尾插 2.尾删 3.头插 4.头删5.打印 6.插入7.删除指定元素 8.删除指定元素的全部9.删除指

定位置的元素10.排序(此文先给出基本的冒泡排序,其他排序算法之后再给出)

下边,我就这些功能一个一个进行说明,尽量配图~~(这里的单链表不带头结点)

为了方便大家读以下的代码,我给出结构体的定义。

typedef struct LinkNode
{
	DataType data;
	struct LinkNode *next;
}LinkNode,*pLinkNode;
typedef struct LinkList
{
	LinkNode *pHead;
}LinkList,*pLinkList;

1.尾插:先要找到链表的尾部,然后进行插入。

具体实现代码如下:

void PushBackLinkList(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode  add = CreatNode(x);
	pLinkNode tmp = pList->pHead;
	if (NULL == pList->pHead)//linklist is empty
	{
		pList->pHead = add;
		add->next = NULL;
		return;
	}
	while (tmp->next)//linklist is not empty
	{
		tmp = tmp->next;
	}
	tmp->next = add;
	add->next = NULL;
	printf("successful  push back\n");
}

2.尾删:顾名思义,找到链表的结尾,将其删除。看图:

下边给出代码实现:

void PopBackLinkList(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode prev = pList->pHead;
	if (NULL == cur->next->next)//linklist only has an element.
	{
		free(cur->next);
		cur->next = NULL;
	}
	else
	{
		while (cur->next)
		{
			prev = cur;
			cur = cur->next;
		}
		free(prev ->next);
		prev->next = NULL;
	}
	printf("successful popback");
}

3.头插:

如果链表是空链表,直接插入就可;有一个元素和有多个元素一样处理。下边图解:

下边给出代码实现:

void PushFrontLinkList(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode  add = CreatNode(x);
	pLinkNode tmp = pList->pHead;
	if (NULL == pList->pHead)//linklist is empty
	{
		pList->pHead = add;
		add->next = NULL;
		return;
	}
	add->next = tmp;
	pList->pHead = add;
	printf("successful pushfront.\n");
}

4.头删:

如果链表是空,不删除;如果是一个结点,删除后将头指针置为NULL;如果是多个结

点,调整指针就好。图解:

下边给出代码实现:

void PopFrontLinkList(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode tmp = pList->pHead;
	pLinkNode del = pList->pHead;
	if (NULL == tmp->next->next)
	{
		free(tmp->next);
		pList->pHead = NULL;
	}
	else
	{
		del = tmp->next;
		tmp = tmp->next->next;
		free(del);
	}
	printf("successful popfront.\n");
}

5.打印:这个比较简单。

6.指定位置之前插入指定元素:这个我们需要有个find函数来查找指定位置的指针

我们约定:如果是空链表,直接将元素插在链表中。

下边给出代码:

void InsertLinkList(pLinkList pList, DataType x, pLinkNode pos)//insert the front of pos
{
	assert(pList);
	pLinkNode p = CreatNode(x);
	pLinkNode tmp = pList->pHead;
	if (NULL == pList->pHead)//check:if linklist is empty,we insert the element in the linklist.
	{
		tmp->next = p;
		p->next = NULL;
		return;
	}
	if (pos == pList->pHead->next)
	{
		PushFrontLinkList(pList, x);
		return;
	}
	while (tmp->next  != pos)
	{
		tmp = tmp->next;
	}
	p->next = tmp->next;
	tmp->next = p;
	printf("successful insertion.\n");
}

7.删除指定元素:

如果链表是空,直接返回;如果链表只有一个元素,如果第一个元素就是指定元素,删

除,然后返回;如果多个元素,找到元素直接删除。

代码:

void Remove(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode del = pList->pHead;
	pLinkNode prev = pList->pHead;
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	if (cur->next == NULL)//只有一个元素
	{
		if (cur->data == x)
		{
			free(cur->next);
			pList->pHead = NULL;
			return;
		}
	}
	else
	{
		while (cur != NULL)
		{
			if (cur->data == x)
			{
				del = cur;
				pList->pHead = cur->next;
				free(del);
				return;
			}
			cur = cur->next;
			while (cur != NULL)
			{
				if (cur->data == x)
				{
					prev->next = cur->next;
					free(cur);
					return;
				}
				prev = cur;
				cur = cur->next;
			}
		}
	}
	printf("successful remove.\n");
}

8.删除指定元素的全部:

给定元素x,删除链表中所有data为x的元素。如果是空链表,直接返回。先判断链表的

第一个元素。

给出代码:

void RemoveAll(pLinkList pList, DataType x)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode prev = pList->pHead;

	while (cur != NULL)      //判断第一个结点
	{
		if (cur->next == NULL)    //linklist has one element.
		{
			if (cur->data == x)
			{
				free(cur->next);
				pList->pHead = NULL;
				return;
			}
		}
		else if (pList->pHead->data == x) //如果不是一个结点,且第一个结点的数据是x
		{
			pList->pHead = cur->next;
			free(cur);
			cur = pList->pHead;
		}
		else
			break;
	}
	cur = cur->next;
	prev = pList->pHead;
	while (cur)
	{
		if (cur->data == x)
		{
			prev->next = cur->next;
			free(cur);
			cur = prev;
		}
		prev = cur;
		cur = cur->next;
	}
	printf("successful removeall.\n");
}

9.删除指定位置的元素:

如果链表是空,直接返回;如果只有一个元素,如果这个元素就是pos位置,删除,返

回;如果多个元素,同样先判断第一个位置,如果是,直接删除,返回,如果不是,继

续向后找。

代码:

void Erase(pLinkList pList, pLinkNode pos)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode del = pList->pHead;
	pLinkNode prev = pList->pHead;
	if (cur->next == NULL)//如果只有一个元素
	{
		if (pos == cur)
		{                       //第一个结点就是pos位置
			free(pList->pHead);
			pList->pHead = NULL;
		}
		return;
	}
	if (pos == cur)
	{                       //第一个结点就是pos位置
		del = cur;
		pList->pHead = cur->next;
		free(del);
		return;
	}
	cur = cur->next;
	while(cur)
	{
		if(cur == pos)
		{
			prev->next = cur->next;
			free(cur);
			return;
		}
		prev = cur;
		cur = cur->next;
	}
}

10.冒泡排序:

给出代码:

void BottleSort(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead || NULL == pList -> pHead->next )
	{
		printf("linklist is empty or linklist has one element.\n");
		return;
	}
	pLinkNode front = pList->pHead;
	pLinkNode tail = NULL;
	while (front != tail)
	{
		while (front->next != tail)
		{
			if (front->data > front->next->data)
			{
				DataType tmp = front->data;
				front->data = front->next->data;
				front->next->data = tmp;
			}
			front = front->next;
		}
		tail = front;
		front = pList->pHead;
	}
}

为了方便读者理解,下边给出程序源码:

//LinkList.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <assert.h>
#include<stdlib.h>
typedef int DataType;
enum OP
{
	EXIT,
	PUSHBACK,
	POPBACK,
	PUSHFRONT,
	POPFRONT,
	PRINT,
	INSERT,
	REMOVE,
	REMOVEALL,
	ERASE,
	SORT
};
typedef struct LinkNode
{
	DataType data;
	struct LinkNode *next;
}LinkNode,*pLinkNode;
typedef struct LinkList
{
	LinkNode *pHead;
}LinkList,*pLinkList;
void InitLinkList(pLinkList pList);
void DestroyLinkList(pLinkList pList);
void PushBackLinkList(pLinkList pList,DataType x);
void PopBackLinkList(pLinkList pList);
void PushFrontLinkList(pLinkList pList, DataType x);
void PopFrontLinkList(pLinkList pList);
void PrintLinkList(pLinkList pList);
void InsertLinkList(pLinkList pList, DataType x, pLinkNode pos);
void Remove(pLinkList pList, DataType x);
void RemoveAll(pLinkList pList, DataType x);
void Erase(pLinkList pList, pLinkNode pos);
void BottleSort(pLinkList pList);
void menu();
#endif//__LINKLIST_H__

//LinkList.c
#include"LinkList.h"
pLinkNode CreatNode(DataType x)
{
	pLinkNode p = (pLinkNode)malloc(sizeof(LinkNode));
	if (NULL == p)
	{
		printf("out of memory.\n");
		exit(EXIT_FAILURE);
	}
	p->data = x;
	return p;
}
pLinkNode find(pLinkList pList,DataType x)
{
	assert(pList);
	pLinkNode tmp = pList->pHead;
	if (pList->pHead == NULL)
	{
		printf("pList is empty.\n");
	}
	while (tmp->data != x)
	{
		tmp = tmp->next;
	}
	return tmp;
}
void InitLinkList(pLinkList pList)
{
	assert(pList);
	pList ->pHead = NULL;
}
void DestroyLinkList(pLinkList pList)
{
	assert(pList);
	pLinkNode p = pList->pHead;
	pLinkNode del = NULL;
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	while (p)
	{
		pList->pHead = p->next;
		free(p);
		p = pList->pHead;
	}
	pList->pHead = NULL;
}
void PushBackLinkList(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode  add = CreatNode(x);
	pLinkNode tmp = pList->pHead;
	if (NULL == pList->pHead)//linklist is empty
	{
		pList->pHead = add;
		add->next = NULL;
		return;
	}
	while (tmp->next)//linklist is not empty
	{
		tmp = tmp->next;
	}
	tmp->next = add;
	add->next = NULL;
	printf("successful  push back\n");
}
void PopBackLinkList(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode prev = pList->pHead;
	if (NULL == cur->next->next)//linklist only has an element.
	{
		free(cur->next);
		cur->next = NULL;
	}
	else
	{
		while (cur->next)
		{
			prev = cur;
			cur = cur->next;
		}
		free(prev ->next);
		prev->next = NULL;
	}
	printf("successful popback");
}
void PushFrontLinkList(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode  add = CreatNode(x);
	pLinkNode tmp = pList->pHead;
	if (NULL == pList->pHead)//linklist is empty
	{
		pList->pHead = add;
		add->next = NULL;
		return;
	}
	add->next = tmp;
	pList->pHead = add;
	printf("successful pushfront.\n");
}
void PopFrontLinkList(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode tmp = pList->pHead;
	pLinkNode del = pList->pHead;
	if (NULL == tmp->next->next)
	{
		free(tmp->next);
		pList->pHead = NULL;
	}
	else
	{
		del = tmp->next;
		tmp = tmp->next->next;
		free(del);
	}
	printf("successful popfront.\n");
}
void PrintLinkList(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode tmp = pList->pHead;
	while (tmp)
	{
		printf("%d->",tmp->data);
		tmp = tmp->next;
	}
	printf("over\n");
}
void InsertLinkList(pLinkList pList, DataType x, pLinkNode pos)//insert the front of pos
{
	assert(pList);
	pLinkNode p = CreatNode(x);
	pLinkNode tmp = pList->pHead;
	if (NULL == pList->pHead)//check:if linklist is empty,we insert the element in the linklist.
	{
		tmp->next = p;
		p->next = NULL;
		return;
	}
	if (pos == pList->pHead->next)
	{
		PushFrontLinkList(pList, x);
		return;
	}
	while (tmp->next  != pos)
	{
		tmp = tmp->next;
	}
	p->next = tmp->next;
	tmp->next = p;
	printf("successful insertion.\n");
}
void Remove(pLinkList pList, DataType x)
{
	assert(pList);
	pLinkNode cur = pList->pHead;
	pLinkNode del = pList->pHead;
	pLinkNode prev = pList->pHead;
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	if (cur->next == NULL)//只有一个元素
	{
		if (cur->data == x)
		{
			free(cur->next);
			pList->pHead = NULL;
			return;
		}
	}
	else
	{
		while (cur != NULL)
		{
			if (cur->data == x)
			{
				del = cur;
				pList->pHead = cur->next;
				free(del);
				return;
			}
			cur = cur->next;
			while (cur != NULL)
			{
				if (cur->data == x)
				{
					prev->next = cur->next;
					free(cur);
					return;
				}
				prev = cur;
				cur = cur->next;
			}
		}
	}
	printf("successful remove.\n");
}
void RemoveAll(pLinkList pList, DataType x)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode prev = pList->pHead;

	while (cur != NULL)      //判断第一个结点
	{
		if (cur->next == NULL)    //linklist has one element.
		{
			if (cur->data == x)
			{
				free(cur->next);
				pList->pHead = NULL;
				return;
			}
		}
		else if (pList->pHead->data == x) //如果不是一个结点,且第一个结点的数据是x
		{
			pList->pHead = cur->next;
			free(cur);
			cur = pList->pHead;
		}
		else
			break;
	}
	cur = cur->next;
	prev = pList->pHead;
	while (cur)
	{
		if (cur->data == x)
		{
			prev->next = cur->next;
			free(cur);
			cur = prev;
		}
		prev = cur;
		cur = cur->next;
	}
	printf("successful removeall.\n");
}

void Erase(pLinkList pList, pLinkNode pos)
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("linklist is empty.\n");
		return;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode del = pList->pHead;
	pLinkNode prev = pList->pHead;
	if (cur->next == NULL)//如果只有一个元素
	{
		if (pos == cur)
		{                       //第一个结点就是pos位置
			free(pList->pHead);
			pList->pHead = NULL;
		}
		return;
	}
	if (pos == cur)
	{                       //第一个结点就是pos位置
		del = cur;
		pList->pHead = cur->next;
		free(del);
		return;
	}
	cur = cur->next;
	while(cur)
	{
		if(cur == pos)
		{
			prev->next = cur->next;
			free(cur);
			return;
		}
		prev = cur;
		cur = cur->next;
	}
}
void BottleSort(pLinkList pList)
{
	assert(pList);
	if (NULL == pList->pHead || NULL == pList -> pHead->next )
	{
		printf("linklist is empty or linklist has one element.\n");
		return;
	}
	pLinkNode front = pList->pHead;
	pLinkNode tail = NULL;
	while (front != tail)
	{
		while (front->next != tail)
		{
			if (front->data > front->next->data)
			{
				DataType tmp = front->data;
				front->data = front->next->data;
				front->next->data = tmp;
			}
			front = front->next;
		}
		tail = front;
		front = pList->pHead;
	}
}
void menu()
{
	printf("*********1.尾插***************\n");
	printf("*********2.尾删***************\n");
	printf("*********3.头插***************\n");
	printf("*********4.头删***************\n");
	printf("*********5.打印***************\n");
	printf("*********6.插入***************\n");
	printf("*********7.删除指定元素********\n");
	printf("*********8.删除指定的全部*******\n");
	printf("*********9.删除指定位置的元素***\n");
	printf("*********10.排序****************\n");
	printf("*********0.退出*******\n");
}

//test.c
#include"LinkList.h"
void test()
{
	LinkList list;
	pLinkNode pos = NULL;
	InitLinkList(&list);
	int input = 1;
	DataType x = 0;
	DataType y = 0;
	while (input)
	{
		menu();
		printf("please your choice:>");
		scanf("%d",&input);
		switch (input)
		{
		case EXIT:
			DestroyLinkList(&list);
			break;
		case PUSHBACK:
			printf("please input a number of insertion:>");
			scanf("%d",&x);
			PushBackLinkList(&list, x);
			break;
		case POPBACK:
			PopBackLinkList(&list);
			break;
		case PUSHFRONT:
			printf("please input a number of insertion:>");
			scanf("%d", &x);
			PushFrontLinkList(&list, x);
			break;
		case POPFRONT:
			PopFrontLinkList(&list);
			break;
		case PRINT:
			PrintLinkList(&list);
			break;
		case REMOVE:
			printf("please input a number of delete:>");
			scanf("%d", &x);
			Remove(&list, x);
			break;
		case REMOVEALL:
			printf("please input a number of delete:>");
			scanf("%d", &x);
			RemoveAll(&list, x);
			break;
		case ERASE:
			printf("please input a number of delete:>");
			scanf("%d", &x);
			pos = find(&list,x);
			Erase(&list, pos);
			break;
		case SORT:
			BottleSort(&list);
			break;
		case INSERT:
			printf("please input a number of insertion:>");
			scanf("%d", &x);
			printf("please input a number of the data of pos:>");
			scanf("%d", &y);
			pos = find(&list, y);
			InsertLinkList(&list, x, pos);
			break;
		}
	}
}
int main()
{
	test();
	system("pause");
	return 0;
}

就整理这么多,如果有问题,请指出~~

时间: 2024-12-21 12:09:14

单链表的基本实现的相关文章

单链表逆置

重写单链表逆置,熟能生巧- #include <iostream> #include <cstdlib> using namespace std; typedef struct List{ int num; struct List *next; }ListNode,*pListNode; void display(ListNode *pHead) { while(pHead) { cout<<pHead->num<<"--"; pH

02 单链表

线性表之链式存储---单链表 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 // 数据结构 6 typedef struct node 7 { 8 int data; 9 struct node *next; 10 }linkList; 11 12 // 创建单链表,并初始化 13 linkList *linkList_init(void) 14 { 15 linkList *l

(单链表)单链表的整体逆序和局部逆序

题目一:将单链表翻转. 思路:有三种方式. 一:用数组存储单链表的值,然后重新逆序赋值,效率较低. 二:利用三个指针,在原来的基础上进行逆序.这种方法比较实用,效率也高. 三:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾.需要新建一个链表,这种方法和第二种差不多. 这里我就写出第二种方法,比较实用. 代码(方法二): struct ListNode { int val; ListNode *next; ListNode(int x) :

[c语言]单链表的实现

一.基础知识:链表(线性表的链式存储结构) (1)特点:逻辑关系相邻,物理位置不一定相邻. (2)分类: a.不带头节点 b.带头节点 (3)单链表的存储结构: typedef struct SListNode {  DataType data;  struct SListNode* next; }SListNode; 二.代码实现(因避开使用二级指针,所以代码中使用了c++中的引用):此处构造的为不带头节点的链表 (1)sList.h   #pragma once typedef int Da

单链表基本操作

//头文件 #pragma once #include <stdio.h> #include <assert.h> #include <malloc.h> #include <stdlib.h> typedef int DateType; typedef struct LinkNode {  DateType _data;  struct  LinkNode* _next; } LinkNode; void PrintList(LinkNode* pHead

C++单链表的创建与操作

链表是一种动态数据结构,他的特点是用一组任意的存储单元(可以是连续的,也可以是不连续的)存放数据元素.链表中每一个元素成为“结点”,每一个结点都是由数据域和指针域组成的,每个结点中的指针域指向下一个结点.Head是“头指针”,表示链表的开始,用来指向第一个结点,而最后一个指针的指针域为NULL(空地址),表示链表的结束.可以看出链表结构必须利用指针才能实现,即一个结点中必须包含一个指针变量,用来存放下一个结点的地址.结点中只有一个next指针的链表称为单链表,这是最简单的链表结构. 首先定义一个

每日一题3:判断单链表是否相交

由于单链表的特殊性,如果某一链表与另一链表相交,那么从相交的节点开始,以后两个链表的每个节点都相同,因此判断两个链表是否相交,只需判断每条链表的最后一个节点是否相同即可! #include "stdafx.h" #include <iostream> using namespace std; struct list_node { int data; list_node* next; }; list_node* CreateList(int datas[],int n) {

数据结构上机测试2-1:单链表操作A (顺序建表+关键字删除)

数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除.分别输出建立的初始单链表和完成删除后的单链表. 输入 第一行输入数据个数n: 第二行依次输入n个整数: 第三行输入欲删除数据m. 输出 第一行输出原始单链表的长度: 第二行依次输出原始单链表的数据: 第三行输出完成删除后的单链表长度: 第四行依次输出完成删除后的

大话数据结构---单链表

单链表在存储结构上与顺序存储的区别:不用开辟连续的存储空间,存储位置任意,只需要让数据的前驱知道它的位置就可以,而使用单链表示只需要知道单链表的第一个元素就能找到其他所有的元素,为了方便 一般会设置一个头指针指向第一个元素. 单链表的数据读取:通过头指针一个一个往后遍历 单链表的插入: 删除: 自定义单链表的简单实现: package com.neuedu.entity; /* * 项目名称:JavaSqList * @author:wzc * @date 创建时间:2017年9月2日 上午9:

数据结构(三)之单链表反向查找

一.反向查找单链表 1.简单查找 先遍历获取单链表单长度n,然后通过计算得到倒数第k个元素的下标为n-k,然后查找下标为n-k的元素. 2.优化查找 先找到下标为k的元素为记录点p1,然后设置新的记录点p2的下标从0开始,同时遍历两个记录点,直到p1的值为null,p2是倒数第k个元素. 单链表结点: package cn.edu.scau.mk; /** * * @author MK * @param <T> */ public class Node<T> { private T