//头文件
#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) //打印
{
LinkNode* begin = pHead;
while (begin != NULL)
{
printf("%d->", begin->_data);
begin = begin->_next; //这里要注意,不要写反了:begin->_next=begin;
}
printf("NULL\n");
}
LinkNode* BuyNode(DateType x) //初始化节点
{
LinkNode* tmp = (LinkNode*)malloc(sizeof(LinkNode));
if (tmp == NULL)
{
printf("malloc faile");
exit(-1);
}
tmp->_next = NULL;
tmp->_data = x;
return tmp;
}
void PushFront(LinkNode*& pHead, DateType x)//头插
{
//空链表
if (pHead == NULL) //证明是空链表,需要开辟节点
{
pHead = BuyNode(x);
}
else
{
LinkNode* nowNode = BuyNode(x);
nowNode->_next = pHead; //把头指针的节点给我的_next,我就指向你,实现了前叉
pHead = nowNode;
}
}
void PopFront(LinkNode*& pHead)//头删,有三种情况:
{
if (pHead == NULL) // 空
{
return;
}
else if (pHead->_next == NULL) // 一个节点
{
free(pHead);
pHead = NULL;
}
else // 两个及以上节点
{
LinkNode*del = pHead; //先保存后面的节点,再来把前面的删了
pHead = pHead->_next;
free(del);
}
}
void PushBack(LinkNode*& pHead, DateType x)//尾插
{
//空
if (pHead == NULL) //证明是空链表,需要开辟节点
{
pHead = BuyNode(x);
}
else
{
LinkNode* tail = pHead;
while (tail->_next != NULL) //注意循环的条件不能写成 tail != NULL
{
tail = tail->_next;
}
tail->_next = BuyNode(x);
}
}
void PopBack(LinkNode*& pHead) //尾删
{
if (pHead == NULL) //没有节点
{
return;
}
else if (pHead->_next == NULL) //一个节点
{
free(pHead);
pHead = NULL;
}
else // 两个节点及以上
{
//LinkNode* cur = pHead; //这里需要两个指针,一前一后,因为删除后一个节点需要前一个节点
//LinkNode* prev = NULL;
//while (cur->_next != NULL) //注意循环的条件不能写成 cur != NULL
//{
// prev = cur;
// cur = cur->_next;
//}
//prev->_next = NULL;
//free(cur);
//或者下面这种方法:
LinkNode* prevTail = pHead;
while (prevTail->_next->_next!=NULL)
{
prevTail = prevTail->_next;
}
free(prevTail->_next);
prevTail->_next = NULL;
}
}
LinkNode* Find(LinkNode* pHead,DateType x)// 找一个数
{
LinkNode* cur = pHead;
while (cur)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
void Insert(LinkNode* pos, DateType x) //任意位置插入
{
LinkNode* tmp = BuyNode(x);
assert(pos);
tmp->_next = pos->_next; //这边要特别注意,
pos->_next = tmp;
/*LinkNode* tmp = BuyNode(x);
LinkNode* next = NULL;
assert(pos);
next = pos->_next;
pos->_next = tmp;
tmp->_next = next;*/
}
void Erase(LinkNode*& pHead,LinkNode* pos) //删除一个节点
{
assert(pos);
//pos是头结点
//pos是中间节点
if (pHead == pos) //只有一个节点
{
LinkNode* del = pos;
pHead = pHead->_next;
free(del);
}
else //有多个节点情况
{
//pos不在链表中的情况
LinkNode* prev = pHead;
while (prev && prev->_next != pos)
{
prev = prev->_next;
}
if (prev)
{
prev->_next = pos->_next;
free(pos);
}
}
}
LinkNode* Reverse(LinkNode*& pHead) //逆置链表
{
LinkNode* cur = pHead;
LinkNode* newHead = NULL;
LinkNode* tmp;
while (cur)
{
tmp = cur;
cur = cur->_next;
tmp->_next = newHead;
newHead = tmp;
}
return newHead;
}
LinkNode* FindMidNode(LinkNode* pHead) //找中间节点
{
LinkNode* first = pHead;
LinkNode* second = pHead;
while (second->_next != NULL)
{
if (second->_next->_next == NULL)
{
return first;
break;
}
else
{
first = first->_next;
second = second->_next->_next;
}
}
return first;
}
LinkNode* FindNodeFromBack(LinkNode* pHead, int x)//找倒数第x个节点
{
int i = 0;
LinkNode*first = pHead;
LinkNode*second = pHead;
while (first && (i < x))
{
first = first->_next;
i++;
}
if (i < x)
{
return NULL;
}
while (first)
{
first = first->_next;
second = second->_next;
}
return second;
}
//删除一个无头单链表的非尾节点
int GetListLength(LinkNode* pHead) //获取链表长度
{
int count = 0;
LinkNode* begin = pHead;
while (begin)
{
count++;
begin = begin->_next;
}
return count;
}
void DestoryList(LinkNode*& pHead) //删除所有节点
{
LinkNode* begin = pHead;
while (begin)
{
LinkNode* del = begin;
begin = begin->_next;
free(del);
}
pHead = NULL;
}
//源文件
#include "Slist.h"
void Test1()//头操作
{
LinkNode* pHead = NULL; //头指针
PushFront(pHead, 1);
PushFront(pHead, 2);
PushFront(pHead, 3);
PushFront(pHead, 4);
PrintList(pHead);//打印
PopFront(pHead);
PopFront(pHead);
PopFront(pHead);
PopFront(pHead);
PopFront(pHead);
PrintList(pHead);//打印
}
void Test2()//尾操作
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PrintList(pHead);//打印
PopBack(pHead);
PopBack(pHead);
PopBack(pHead);
PopBack(pHead);
PopBack(pHead);
PrintList(pHead);//打印
}
void Test3()//获取链表长度
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PrintList(pHead);//打印
int ret = GetListLength(pHead);
printf("%d\n",ret);
}
void Test4()//删除整个链表
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PrintList(pHead);//打印
DestoryList(pHead);
PrintList(pHead);
}
void Test5()//找一个数,找到这个数后插入一个数
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PrintList(pHead);
LinkNode* ret = Find(pHead, 2);
printf("%d\n", ret->_data);
Insert(ret, 8); //找到2后,在2后面插个8
PrintList(pHead);
ret = Find(pHead, 7); //7不存在
printf("ret=NULL:%p\n", ret);
}
void Test6() //删除指定位置的数
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PrintList(pHead);
LinkNode* ret = Find(pHead, 2);
Erase(pHead,ret); //找到2后,把2删除
PrintList(pHead);
}
void Test7() //找中间节点
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PushBack(pHead, 5);
PushBack(pHead, 6);
//PushBack(pHead, 7);
PrintList(pHead);
LinkNode* ret=Reverse(pHead);
PrintList(ret);
/*LinkNode*ret=FindMidNode(pHead);
printf("%d\n", ret->_data);*/
}
void Test8() //返回倒数第k个节点
{
LinkNode* pHead = NULL;
PushBack(pHead, 1);
PushBack(pHead, 2);
PushBack(pHead, 3);
PushBack(pHead, 4);
PushBack(pHead, 5);
PushBack(pHead, 6);
PrintList(pHead);
LinkNode* ret = FindNodeFromBack(pHead,3);
printf("%d\n", ret->_data);
/*LinkNode*ret=FindMidNode(pHead);
printf("%d\n", ret->_data);*/
}
int main()
{
//Test1();
//Test2();
//Test3();
//Test4();
//Test5();
//Test6();
//Test7();
Test8();
return 0;
}
转载于:https://blog.51cto.com/10706198/1715578