C语言单链表的实现

 更新时间:2016年04月13日 14:28:37   作者:Lynn-Zhang  
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。这篇文章主要介绍了C语言单链表的实现 的相关资料,需要的朋友可以参考下

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

链表结构:

SList.h

#pragma once
typedef int DataType;
typedef struct SListNode
{
DataType data;
struct SListNode* next;
}SListNode;
// 如果要修改链表就必须加引用
SListNode* _BuyNode(DataType x); //建立节点
void PrintSlist(SListNode* pHead); //打印单链表
void PushBack(SListNode* & pHead, DataType x); //尾插 (这里用了引用,指明是list的别名,调用时传参,不用传地址)(引用在.c文件中不可用)
//void PushBack(SListNode** pHead, DataType x); // 这里的第一个参数指向链表第一个节点的指针的地址(调用时传参,传的是地址)
void PopBack(SListNode* & pHead); //尾删
void PushFront(SListNode* & pHead, DataType x); //头插
void PopFront(SListNode* & pHead); //头删
void DestoryList(SListNode*& pHead); //清空整个链表
int GetSize(SListNode* pHead); //获取链表长度
SListNode* Find(SListNode* pHead, DataType x); //查找
void Insert(SListNode* pos, DataType x); //某位置后插入数据
void Erase(SListNode*& pHead, SListNode* pos); //删除某位置的数据
void DelNonTailNode(SListNode* pos); //删除一个无头单链表的非尾节点
void InsertFrontNode(SListNode* pos, DataType x); // 在无头单链表的一个非头节点前插入一个节点
SListNode* FindMidNode(SListNode* pHead); //查找中间节点
SListNode* FindKNode(SListNode* pHead, int k); //查找倒数第k个节点(要求只能遍历一次)
void PrintTailToHead(SListNode* pHead); //倒着打印单链表(递归)
//SListNode* Reverse_(SListNode* pHead); //逆置单链表(需要接收返回值),原链表会面目全非
void Reverse(SListNode*& pHead); // 将原链表逆置
SListNode* Merge(SListNode* pHead1, SListNode* pHead2); //合并两个有序链表(合并后依然有序)(递归)
void Sort(SListNode* pHead); //冒泡排序

SList.cpp

#include"SList.h"
#include <stdio.h>
#include<assert.h>
#include <malloc.h>
SListNode* _BuyNode(DataType x) //建立节点
{
SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
tmp->data = x;
tmp->next = NULL;
return tmp;
}
void PrintSlist(SListNode* pHead) // 打印单链表
{
SListNode* cur = pHead;
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
//void PushBack(SListNode** ppHead, DataType x) //尾插
//{
// assert(ppHead);
// // 1.空
// // 2.不为空
// if(*ppHead == NULL)
// {
// *ppHead = _BuyNode(x);
// }
// else
// {
// // 找尾
// SListNode* tail = *ppHead;
// while(tail->next != NULL)
// {
// tail = tail->next;
// }
//
// tail->next = _BuyNode(x);
// }
//}
void PushBack(SListNode* & pHead, DataType x) //尾插
{
// 1.空
// 2.不为空
if (pHead == NULL)
{
pHead = _BuyNode(x);
}
else
{
// 找尾
SListNode* tail = pHead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = _BuyNode(x);
}
}
void PopBack(SListNode* & pHead) // 尾删
{
//
// 1.空
// 2.一个节点
// 3.多个节点
//
if (pHead == NULL)
{
return;
}
else if (pHead->next == NULL)
{
free(pHead);
pHead = NULL;
}
else
{
SListNode* tail = pHead;
SListNode* prev = NULL;
while (tail->next)
{
prev = tail;
tail = tail->next;
}
free(tail);
prev->next = NULL;
}
}
void PushFront(SListNode* & pHead, DataType x) //头插
{
// 1.空
// 2.不空
if (pHead == NULL)
{
pHead = _BuyNode(x);
}
else
{
SListNode* tmp = _BuyNode(x);
tmp->next = pHead;
pHead = tmp;
}
}
void PopFront(SListNode*& pHead) //头删
{
//
// 1.空
// 2.一个节点
// 3.一个以上的节点
//
if (pHead == NULL)
{
return;
}
else if (pHead->next == NULL)
{
free(pHead);
pHead = NULL;
}
else
{
SListNode* tmp = pHead;
pHead = pHead->next;
free(tmp);
}
}
void DestoryList(SListNode*& pHead) //清空整个链表
{
SListNode* cur = pHead;
while (cur)
{
SListNode* tmp = cur;
cur = cur->next;
free(tmp);
}
pHead = NULL;
}
int GetSize(SListNode* pHead) //获取链表长度
{
assert(pHead);
SListNode* cur = pHead;
int count = 0;
while (cur)
{
count++;
cur = cur->next;
}
return count;
}
SListNode* Find(SListNode* pHead, DataType x) //查找节点
{
SListNode* cur = pHead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void Insert(SListNode* pos, DataType x) // 某位置后插入节点
{
assert(pos);
SListNode* tmp = _BuyNode(x);
tmp->next = pos->next;
pos->next = tmp;
}
void Erase(SListNode*& pHead, SListNode* pos) //删除某位置的节点
{
assert(pos);
assert(pHead);
//pos为头结点
if (pHead == pos)
{
pHead = pHead->next;
free(pos);
return;
}
////
SListNode* prev = pHead;
while (prev)
{
if (prev->next == pos)
{
prev->next = pos->next;
free(pos);
break;
}
prev = prev->next;
}
}
void DelNonTailNode(SListNode* pos) //// 删除一个无头单链表的非尾节点
{
assert(pos);
assert(pos->next);
SListNode* del = pos->next;
SListNode* dnext = del->next;
pos->data = del->data;
pos->next = dnext;
free(del);
}
void InsertFrontNode(SListNode* pos, DataType x) // 在无头单链表的一个非头节点前插入一个节点
{
assert(pos);
SListNode* tmp = _BuyNode(pos->data);
tmp->next = pos->next;
pos->next = tmp;
pos->data = x;
}
void Sort(SListNode* pHead) //冒泡排序
{
assert(pHead);
int size = GetSize(pHead);
for (int i = 0; i < size - 1; i++)
{
SListNode* left = pHead;
SListNode* right = pHead->next;
for (int j = 0; j < size - i - 1; j++)
{
if (left->data>right->data)
{
int tmp = left->data;
left->data = right->data;
right->data = tmp;
}
right = right->next;
left = left->next;
}
}
}
SListNode* FindMidNode(SListNode* pHead) //查找中间节点
{
SListNode* fast = pHead;
SListNode* slow = pHead;
while (fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
SListNode* FindKNode(SListNode* pHead, int k) //查找倒数第k个节点
{
SListNode* fast = pHead;
SListNode* slow = pHead;
while (fast && k--)
{
fast = fast->next;
}
if (k > 0)
{
return NULL;
}
while (fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
void PrintTailToHead(SListNode* pHead) //倒着打印单链表(递归)
{
if (pHead)
{
PrintTailToHead(pHead->next);
printf("%d ", pHead->data);
}
}
//SListNode* Reverse_(SListNode* pHead) //逆置单链表(需要接收返回值)原链表会面目全非
//{
// SListNode* cur = pHead;
// SListNode* newHead = NULL;
// while (cur)
// {
// SListNode* tmp = cur;
// cur = cur->next;
// tmp->next = newHead;
// newHead = tmp;
// }
// return newHead;
//}
void Reverse(SListNode*& pHead) //逆置单链表
{
SListNode* cur = pHead;
SListNode* newHead = NULL;
while (cur)
{
SListNode* tmp = cur;
cur = cur->next; 
tmp->next = newHead;
newHead = tmp;
}
pHead = newHead;
//return newHead;
}
SListNode* Merge(SListNode* pHead1, SListNode* pHead2) //合并两个有序链表(合并后依然有序)递归
{
if (pHead1 == NULL)
return pHead2;
else if (pHead2 == NULL)
return pHead1;
SListNode* pMergedHead = NULL;
if (pHead1->data < pHead2->data)
{
pMergedHead = pHead1;
pMergedHead->next = Merge(pHead1->next, pHead2);
}
else
{
pMergedHead = pHead2;
pMergedHead->next = Merge(pHead1, pHead2->next);
}
return pMergedHead;
}

Test.cpp

#include "SList.h"
#include<stdlib.h>
void Test1()
{
// 尾插 打印 尾删 头插 头删 清空链表
SListNode* list = NULL;
PushBack(list, 1);
PushBack(list, 2);
PushBack(list, 3);
PushBack(list, 4);
PrintSlist(list);
PopBack(list);
PrintSlist(list);
PushFront(list,0);
PrintSlist(list);
PopFront(list);
PrintSlist(list);
DestoryList(list);
PrintSlist(list);
}
void Test2()
{
// 查找节点 在某位置插入节点 删除某位置节点 
SListNode* list = NULL;
PushBack(list, 1);
PushBack(list, 2);
PushBack(list, 3);
PushBack(list, 4);
PrintSlist(list);
SListNode* pos = Find(list, 2);
Insert(pos, 0);
PrintSlist(list);
Erase(list, Find(list, 0));
PrintSlist(list);
}
void Test3()
{
SListNode* list = NULL;
PushBack(list, 1);
PushBack(list, 2);
PushBack(list, 3);
PushBack(list, 4);
PushBack(list, 5);
PushBack(list, 6);
PrintSlist(list);
// 删除一个无头单链表的非尾节点 
/*SListNode* pos = Find(list, 2);
DelNonTailNode(pos);
PrintSlist(list);*/
// 在无头单链表的一个非头节点前插入一个节点
/*SListNode* pos = Find(list, 2);
InsertFrontNode(pos, 0);
PrintSlist(list);*/
//查找中间节点
//PrintSlist(FindMidNode(list));
//查找倒数第k个节点
//SListNode* ret = FindKNode(list, 2);
//PrintSlist(ret);
//倒着打印单链表(递归)
//PrintTailToHead(list);
//逆置单链表
//SListNode* ret = Reverse(list);
//PrintSlist(ret);
//PrintSlist(Reverse_(list));
}
void Test4()
{ //合并两个有序链表(合并后依然有序)
SListNode* list = NULL;
PushBack(list, 4);
PushBack(list, 2);
PushBack(list, 1);
PushBack(list, 4);
PrintSlist(list);
Sort(list);
PrintSlist(list);
/*SListNode* list1 = NULL;
PushBack(list1, 2);
PushBack(list1, 3);
PushBack(list1, 3);
PushBack(list1, 0);
PrintSlist(list);
Sort(list1);
PrintSlist(list1);
SListNode* ret = Merge(list, list1);
PrintSlist(ret);
PrintSlist(list);
PrintSlist(list1);*/
}
int main()
{
//Test1();
//Test2();
//Test3();
Test4();
system("pause");
return 0;
}

以上内容是小编给大家介绍的C语言单链表的实现代码,希望对大家有所帮助!

相关文章

  • C++实现数组的排序/插入重新排序/以及逆置操作详解

    C++实现数组的排序/插入重新排序/以及逆置操作详解

    将新的数字与已经排序好的数组中的数字一一比较,直到找到插入点,然后将插入点以后的数字都向后移动一个单位(a[i+1]=a[i]),然后将数据插入即可
    2013-10-10
  • C语言数据结构之双链表&循环链表&静态链表详解

    C语言数据结构之双链表&循环链表&静态链表详解

    这篇文章主要为大家详细介绍了C语言数据结构中双链表&循环链表&静态链表的原理与使用,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-09-09
  • C++实现LeetCode(137.单独的数字之二)

    C++实现LeetCode(137.单独的数字之二)

    这篇文章主要介绍了C++实现LeetCode(137.单独的数字之二),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • 离线安装visual studio2022+QT5.12的实现步骤

    离线安装visual studio2022+QT5.12的实现步骤

    近期有需求离线配置C++与QT环境,本文主要介绍了离线安装visualstudio2022+QT5.12的实现步骤,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • 关于C++数组中重复的数字

    关于C++数组中重复的数字

    这篇文章主要介绍得是关于C++数组中重复的数字,文章以问题描述得形式,对问题展开分析用不同得方法去解决问题并附上方法得详细代码,需要的朋友可以参考以下文章得具体内容
    2021-11-11
  • C语言中getchar( ) 函数使用详解

    C语言中getchar( ) 函数使用详解

    getchar() 字符输入函数,没有参数,从输入缓冲区里面读取一个字,需要注意一次只能读取一个字符,这篇文章主要介绍了C语言中getchar函数使用详解,需要的朋友可以参考下
    2022-12-12
  • C语言编写一个链表

    C语言编写一个链表

    这篇文章主要为大家详细介绍了C语言编写一个链表,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • C++ Virtual关键字的具体使用

    C++ Virtual关键字的具体使用

    这篇文章主要介绍了C++ Virtual关键字的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • C语言动态内存的分配最全面分析

    C语言动态内存的分配最全面分析

    动态内存是相对静态内存而言的。所谓动态和静态就是指内存的分配方式。动态内存是指在堆上分配的内存,而静态内存是指在栈上分配的内存,本文带你深入探究C语言中动态内存的管理
    2022-08-08
  • C/C++中宏/Macro的深入讲解

    C/C++中宏/Macro的深入讲解

    这篇文章主要给大家介绍了关于C/C++中宏/Macro的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C/C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06

最新评论