程序实现了单链表的基本操作,包括创建,初始化,销毁,头插,头删,尾插,尾删,打印单链表,查找指定数据的位置,指定位置插入指定数据,删除指定数据,删除链表里出现的所有指定数据,指定位置删除,单链表的冒泡排序。博主现阶段还是技术小白,此初步调试完成,读者如果发现新的bug,还请不吝赐教!
先介绍一下单链表的概念:
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
链表中的数据是以结点来表示的,每个结点的构成:元素( 数据) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
单链表是链式存取的结构,为找第 i 个 数据元素,必须先找到第 i-1 个数据元素。而且单链表只能从前往后遍历。
接下来分享一下我的实现:
头文件部分:
#define _CRT_SECURE_NO_WARNINGS 1
#ifndef _LINKLIST_H__
#define _LINKLIST_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct LinkNode
{
DataType data;
struct LinkNode *next;
}LinkNode,*pLinkNode;
typedef struct LinkList
{
LinkNode *pHead;
}LinkList,*pLinkList;
void InitLinkList(pLinkList pList); //初始化单链表
void DestroyList(pLinkList pList); //销毁单链表
void PushBack(pLinkList pList, DataType x); //尾插
void PopBack(pLinkList pList); //尾删
void PushFront(pLinkList pList, DataType x); //头插
void PopFront(pLinkList pList); //头删
void PrintList(pLinkList pList); //打印单链表
pLinkNode Find(pLinkList pList, DataType x); //查找指定元素的地址
void Insert(pLinkList pList, pLinkNode pos, DataType x);// 指定位置插入指定数据
void Remove(pLinkList pList, DataType x);//删除指定数据
void RemoveAll(pLinkList pList, DataType x);//删除链表里出现的所有指定数据
void Erase(pLinkList pList, pLinkNode pos); //指定位置删除
void BubbleSort(pLinkList pList); //单链表的冒泡排序
#endif //_LINKLIST_H__
函数实现:
#include"linklist.h"
void InitLinkList(pLinkList pList)
{
assert(pList);
pList->pHead = NULL;
}
void DestroyList(pLinkList pList)
{
assert(pList);
pLinkNode cur;
cur = pList->pHead;
while (cur)
{
pLinkNode del = cur;
cur = cur->next;
free(del);
del = NULL;
}
pList->pHead = NULL;
}
pLinkNode BuyNewNode(DataType x) //创建一个新结点并返回
{
pLinkNode NewNode = NULL;
NewNode = (pLinkNode)malloc(sizeof(LinkNode));
if (NewNode == NULL)
{
printf("out of memory\n");
exit(EXIT_FAILURE);
}
NewNode->data = x;
NewNode->next = NULL;
return NewNode;
}
void PushBack(pLinkList pList, DataType x)
{
assert(pList);
pLinkNode cur=NULL;
pLinkNode NewNode=BuyNewNode(x);
cur = pList->pHead;
if (cur == NULL) //若为空链表直接将新结点设置为头结点
{
pList->pHead = NewNode;
}
else
{
while ((cur->next) != NULL) //找到链表的最后一个位置
{
cur = cur->next;
}
cur->next = NewNode;
}
}
void PopBack(pLinkList pList)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode fcur = NULL;
if (cur == NULL)
{
printf("空表\n");
return;
}
else if (cur->next == NULL) //只有一个结点的情况
{
free(pList->pHead);
pList->pHead = NULL;
}
else //拥有两个以上的结点
{
while (cur->next != NULL)
{
fcur = cur;
cur = cur->next;
}
fcur->next = NULL;
}
}
void PushFront(pLinkList pList, DataType x)
{
assert(pList);
pLinkNode NewNode = BuyNewNode(x);
if (pList->pHead == NULL) //空表的情况
{
pList->pHead = NewNode;
}
else
{
NewNode->next = pList->pHead;
pList->pHead = NewNode;
}
}
void PopFront(pLinkList pList)
{
assert(pList);
if (pList->pHead == NULL) //空表
{
return;
}
else //非空
{
pList->pHead = pList->pHead->next;
}
}
void PrintList(pLinkList pList)
{
assert(pList);
pLinkNode cur;
cur = pList->pHead;
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL");
printf("\n");
}
pLinkNode Find(pLinkList pList, DataType x)
{
assert(pList);
pLinkNode cur = pList->pHead;
while (cur && (cur->data != x))// 当前结点不为指定数据则指针向后移动
{
cur = cur->next;
}
return cur;
}
void Insert(pLinkList pList, pLinkNode pos, DataType x)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode fcur = NULL;
pLinkNode NewNode = BuyNewNode(x);
if (pos == pList->pHead) //若指定位置为头结点
{
NewNode->next = pList->pHead;
pList->pHead = NewNode;
}
else
{
while (cur && (cur != pos))
{
fcur = cur;
cur = cur->next;
}
NewNode->next = cur;
fcur->next = NewNode;
}
}
void Remove(pLinkList pList, DataType x)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode fcur = NULL;
if (cur->data == x) //若指定数据为头结点包含的数据
{
pList->pHead = pList->pHead->next;
}
else
{
while (cur&&(cur->data!=x)) //找到指定数据
{
fcur = cur;
cur = cur->next;
}
if (cur == NULL) //若遍历整个链表后没有找到
{
printf("链表中无该数据\n");
}
else //找到了删除
{
fcur->next = cur->next;
free(cur);
cur = NULL;
}
}
}
void RemoveAll(pLinkList pList, DataType x)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode fcur = NULL;
pLinkNode del = NULL;
if (cur == NULL) //空表
{
return;
}
if ((cur->data == x)&&(cur->next == NULL)) //表中只有一个结点。
{
free(cur);
cur = NULL;
}
else if (cur->data == x) //若要删除的数据是头结点
{
PopFront(pList);
}
while (cur &&(cur->next)) //循环找到所有指定的数据删除
{
if(cur->next->data == x)
{
del = cur->next;
cur->next = del->next;
free(del);
del = NULL;
}
cur = cur->next;
}
}
void Erase(pLinkList pList, pLinkNode pos)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode fcur = NULL;
if (pos == pList->pHead) //若指定位置是头结点的位置,调用头删函数
{
PopFront(pList);
}
else
{
while (cur)
{
while (cur != pos) //循环找到指定位置
{
fcur = cur;
cur = cur->next;
}
if (cur == NULL)
{
printf("无数据存放在该位置\n");
return;
}
else
{
fcur->next = cur->next;
free(cur);
cur = NULL;
}
}
}
}
void BubbleSort(pLinkList pList)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode inCur = pList->pHead;
pLinkNode checkNode = NULL;
DataType tmp = 0;
int count = 0; //用来优化冒泡排序
while (cur->next)
{
while (inCur->next != checkNode)
{
if (inCur->data > inCur->next->data)
{
tmp = inCur->data;
inCur->data = inCur->next->data;
inCur->next->data = tmp;
count++;
}
inCur = inCur->next;
}
if (count == 0)
{
return;
}
checkNode = inCur;//j<size-1-i;
inCur = pList->pHead;
cur = cur->next;
}
}
主函数部分(主要用来测试):
#include"linklist.h"
test1()
{
LinkList list;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PopBack(&list);
PopBack(&list);
PrintList(&list);//测试尾插和尾删,应该输出1->NULL;
DestroyList(&list);
}
test2()
{
LinkList list;
pLinkNode ret = NULL;
InitLinkList(&list);
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PopFront(&list);
PrintList(&list); //测试头插和头删,应该输出2->1->NULL
ret = Find(&list, 1);
if (ret == NULL)
{
printf("链表中不存在该数据");
}
Remove(&list, 1);
PrintList(&list);//测试删除指定数据函数,应该输出2->NULL
DestroyList(&list);
}
test3()
{
LinkList list;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 1);
PushBack(&list, 2);
PrintList(&list);
RemoveAll(&list, 1); //测试指定链表中存在的所有某个数据,调用后应输出2->3->2->NULL
PrintList(&list);
DestroyList(&list);
}
test4()
{
LinkList list;
pLinkNode ret = NULL;
InitLinkList(&list);
PushFront(&list, 1);
PushFront(&list, 5);
PushFront(&list, 3);
PushFront(&list, 7);
PushFront(&list, 9);
PushFront(&list, 0);
PrintList(&list);
BubbleSort(&list); //测试冒泡排序,输出一个无序,调用后输出有序
PrintList(&list);
DestroyList(&list);
}
test5()
{
LinkList list;
pLinkNode ret = NULL;
InitLinkList(&list);
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PrintList(&list);
ret = Find(&list, 1);
if (ret == NULL)
{
printf("链表中不存在该数据");
}
Insert(&list, ret, 3); //测试指定位置插入指定数据,调用后输出3->2->3->1->NULL;
PrintList(&list);
DestroyList(&list);
}
test6()
{
LinkList list;
pLinkNode ret = NULL;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PrintList(&list);
ret = Find(&list, 1);
if (ret == NULL)
{
printf("链表中不存在该数据");
}
Erase(&list, ret); //测试指定位置删除,调用后应输出2->3->NULL
PrintList(&list);
DestroyList(&list);
}
int main()
{
test1();
test2();
test3();
test4();
test5();
test6();
getchar();
return 0;
}