单链表基本操做

2021年09月15日 阅读数:1
这篇文章主要向大家介绍单链表基本操做,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。
//头文件
#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;
}