數據結構---不帶頭結點的單項非循環鏈表

因爲順序表的底層空間是連續的,所以如果對元素進行大量的任意位置添加或刪除,在順序表裏就要移動大量的元素,效率很低,因此我們需要讓元素存儲在不連續的空間中,但如果直接存儲,就不知道它的下一個元素是什麼,這時就可以利用鏈表這個結構
鏈表是一種物理存儲結構上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的鏈接次序實現(除了存儲元素信息外,還要給下一個節點的位置)
找到第一個節點,就可以通過鏈式結構找到下一個節點
鏈表:
1.單鏈表(從前往後)、雙鏈表(循環)
2.帶頭(鏈表中第一個節點的不存儲有效數據)
不帶頭(一個節點存儲有效數據)
3.循環、非循環

下面來實現下不帶頭結點的單項非循環鏈表

SList.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
//無頭單項非循環
//不帶頭結點,第一個結點存的是有效元素
typedef int SDataType;
//節點的結構  
typedef struct SListNode
{
 SDataType _data;//保存數據
 struct SListNode* _pNext;//指向下一個 節點的地址
}Node;
//鏈表的結構
//把鏈表記錄下來,只要知道頭節點就行
typedef struct SList
{
 Node* _pHead;
}SList,*PSList;

void SListInit(PSList pl);//初始化
void SListDestory(PSList pl);//銷燬

Node* BuySListNode(SDataType data);

void SListPushBack(PSList pl, SDataType data);//尾插
void SListPopBack(PSList pl);//尾刪

void SListPushFront(PSList pl, SDataType data);//頭插
void SListPopFront(PSList pl);//頭刪

Node* SListFind(PSList pl, SDataType data);//找位置
void SListInsert(PSList pl, Node* pos, SDataType data);//任意位置插入
void SListErase(PSList pl, Node* pos);//任意位置刪除

void SListIsFindData(PSList pl, SDataType data);//檢測data是否在鏈表中
void SListRemove(PSList pl, SDataType data);// 移除鏈表中第一個值爲data的元素 
//void SListRemoveAll(PSList pl, SDataType data);// 移除鏈表中所有值爲data的元素 

void SListSize(PSList pl);//// 獲取鏈表有效元素個數 
void SListCapacity(PSList pl);// 獲取鏈表的容量 
int SListEmpty(PSList pl);// 檢測鏈表是否爲空

SDataType SListFront(PSList pl);// 獲取鏈表中第一個元素 
SDataType SListBack(PSList pl);// 獲取鏈表中最後一個元素
///////////////////////////////////////////////////////
void PrintSList(PSList pl);
//////////////////////////////////
void SListTest();

SList.c文件

#include "SList.h"
void SListInit(PSList pl)//初始化
{
 assert(pl);
 pl->_pHead = NULL; 
}
Node* BuySListNode(SDataType data)//獲取新結點
{
 Node* pNode = (Node*)malloc(sizeof(Node));
 if (pNode == NULL)
 {
  assert(0);
  return NULL;
 }
 pNode->_data = data;
 pNode->_pNext = NULL;
 return pNode;
}
void SListPushBack(PSList pl, SDataType data)//尾插
{
 Node* pNewNode = NULL;//新結點
 Node* pCur = NULL;//鏈表最後一個結點
 assert(pl);
 pNewNode = BuySListNode(data);
 pCur = pl->_pHead;
 //檢測鏈表是否爲空
 if (pl->_pHead == NULL)
  pl->_pHead = pNewNode;
 else
 {
  while (pCur->_pNext)
  {
   pCur = pCur->_pNext;
  }
  pCur->_pNext = pNewNode;
 }
}
void SListPopBack(PSList pl)//尾刪
{
 //找鏈表中最後一個結點,保存前一個結點(或倒數第二個結點)  鏈表至少有兩個結點
 assert(pl);
 if (pl->_pHead == NULL)
 {
  printf("空鏈表\n");
  return;
 }
 else if (pl->_pHead->_pNext == NULL)//有一個結點
 {
  free(pl->_pHead);
  pl->_pHead = NULL;
 }
 else//至少有兩個結點
 {
  Node* pCur = pl->_pHead;
  Node* pre = NULL;
  while (pCur->_pNext)
  {
   pre = pCur;//保存pCur的前一個結點
   pCur = pCur->_pNext;
  }
  free(pCur);
  pre->_pNext = NULL;
 }
}
void SListPushFront(PSList pl, SDataType data)//頭插
{
 Node* pNewNode = NULL;
 assert(pl);
 pNewNode = BuySListNode(data);
 pNewNode->_pNext = pl->_pHead;;
 pl->_pHead = pNewNode;
}
void SListPopFront(PSList pl)//頭刪
{
 assert(pl);
 if (pl->_pHead == NULL)//無結點
 {
  printf("空鏈表\n");
  return;
 }
 else
 {
  Node* DeleteNode = pl->_pHead;
  pl->_pHead = pl->_pHead->_pNext;
  free(DeleteNode);
 }
}
Node* SListFind(PSList pl, SDataType data)//找位置
{
 assert(pl);
 Node* pCur = pl->_pHead;
 while (pCur)
 {
  if (pCur->_data == data)
   return pCur;
  pCur = pCur->_pNext;
 }
 return NULL;
}
void SListInsert(PSList pl, Node* pos, SDataType data)//任意位置插入(插在後面)
{
 Node* pNewNode = NULL;
 assert(pl);
 pNewNode = BuySListNode(data);
 pNewNode->_pNext = pos->_pNext;
 pos->_pNext = pNewNode;
 printf("插入成功:");
}
void SListErase(PSList pl, Node* pos)//任意位置刪除
{
 Node* prePos = NULL;
 assert(pl);
 if (pl->_pHead == NULL||pos==NULL)
 {
  printf("鏈表爲空或位置,無法刪除\n");
  return;
 }
 if (pos == pl->_pHead)//pos剛好在第一個結點的位置
  pl->_pHead = pos->_pNext;
 else
 {
  prePos = pl->_pHead;
  while (prePos->_pNext != pos)
  {
   prePos = prePos->_pNext;
  }
  prePos->_pNext = pos->_pNext;
 }
 free(pos);
 printf("刪除成功:");
}
void SListIsFindData(PSList pl, SDataType data)//檢測data是否是鏈表中
{
 assert(pl);
 Node* pCur = pl->_pHead;
 if (pl->_pHead == NULL)
 {
  printf("鏈表爲空,無法檢測");
  return;
 }
 while (pCur)
 {
  if (pCur->_data == data)
  {
   printf("%d在鏈表中", data);
   return;
  }
  pCur = pCur->_pNext;
 }
 printf("%d不在鏈表中",data);
 return;
}
void SListRemove(PSList pl, SDataType data)// 移除鏈表中第一個值爲data的元素
{
 assert(pl);
 if (pl->_pHead == NULL)
 {
  printf("鏈表爲空,無法移除元素\n");
  return;
 }
 Node* pCur = pl->_pHead;
 Node* pPre = NULL;//pCur前一個結點
 while (pCur->_pNext!=NULL)
 {
  while (pCur->_data != data)
  {
   if (pCur->_pNext == NULL)
   {
    printf("很遺憾,沒有找到:");
    return;
   }
   pPre = pCur;
   pCur = pCur->_pNext;
  }
  if (pCur->_data==data)
  {
   if (pPre == NULL)
    pl->_pHead = pCur->_pNext;
   else
    pPre->_pNext = pCur->_pNext;
   free(pCur);
   pCur = NULL;
   printf("移除成功:   ");
   return;
  }
 } 
}
//void SListRemoveAll(PSList pl, SDataType data)// 移除鏈表中所有值爲data的元素
//{
// assert(pl);
// if (pl->_pHead == NULL)
// {
//  printf("鏈表爲空,無法移除元素\n");
//  return;
// }
// Node* pCur = pl->_pHead;
// Node* pPre = NULL;//pCur的前一個結點
// while (pCur->_pNext!=NULL)
// {
//  if (pCur->_data != data)
//  {
//   pPre = pCur;
//   pCur = pCur->_pNext;
//  }
//  else
//  {
//   if (pPre == NULL)
//    pl->_pHead = pCur->_pNext;
//   else
//    pPre->_pNext = pCur->_pNext;
//   free(pCur);
//   pCur = NULL; 
//  }
// }
//}
void SListSize(PSList pl)//// 獲取鏈表有效元素個數 
{
 assert(pl);
 int count = 1;
 Node* pCur = pl->_pHead;
 while (pCur->_pNext)
 {
  if (pCur->_pNext)
   pCur = pCur->_pNext;
  count++;
 }
 printf("有效元素個數爲:%d  :", count);
 return;
}
int SListEmpty(PSList pl)// 檢測鏈表是否爲空
{
 assert(pl);
 if (pl->_pHead)
 {
  printf("鏈表不爲空:");
  return 0;
 }
 printf("鏈表爲空:");
 return 0;
}
SDataType SListFront(PSList pl)// 獲取鏈表中第一個元素 
{
 assert(pl);
 printf("鏈表中第一個元素爲:%d:  ", pl->_pHead->_data);
 return pl->_pHead->_data;
}
SDataType SListBack(PSList pl)// 獲取鏈表中最後一個元素
{
 assert(pl);
 Node* pCur = pl->_pHead;
 while (pCur->_pNext)
 {
  pCur = pCur->_pNext;
 }
 printf("鏈表中最後一個元素爲:%d:   ", pCur->_data);
 return pCur->_data;
}
void SListDestory(PSList pl)//銷燬
{ 
 Node* pCur = NULL;
 assert(pl);
 pCur = pl->_pHead;
 while (pCur)
 { 
  pl->_pHead = pCur->_pNext;//下個結點爲第一個結點了
  free(pCur);
  pCur = pl->_pHead;
 }
 pl->_pHead = NULL;
 printf("銷燬成功:");
}
//////////////////////////////////////
void PrintSList(PSList pl)
{
 Node* pCur = NULL;
 assert(pl);
 pCur = pl->_pHead;
 while (pCur)
 {
  printf("%d-->", pCur->_data);
  pCur = pCur->_pNext;
 }
 printf("NULL\n");
}

test.c文件

#include "SList.h"
int main()
{
  SList s;
  SListInit(&s);
  SListPushBack(&s, 0);//尾插
  SListPushBack(&s, 0);
  SListPushBack(&s, 1);
  SListPushBack(&s, 1);
  SListPushBack(&s, 2);
  SListPushBack(&s, 2);
  SListPushBack(&s, 4);
  SListPushBack(&s, 4);
  SListPushBack(&s, 5);
  SListPushBack(&s, 5);
  SListPushBack(&s, 7);
  SListPushBack(&s, 8);
  SListPushBack(&s, 9);
  SListPushBack(&s, 9);
  PrintSList(&s);
  
  SListPopBack(&s);//尾刪
  PrintSList(&s);
  SListPushFront(&s, 0);//頭插
  PrintSList(&s);
  SListPopFront(&s);//頭刪
  PrintSList(&s);
  
  //任意位置插入
  Node* ret = SListFind(&s, 2);//找位置
  SListInsert(&s, ret, 8);
  PrintSList(&s);
  
  //任意位置刪除
  ret = SListFind(&s, 2);
  SListErase(&s, ret);
  PrintSList(&s);
  
  //檢測data是否是鏈表中
  SListIsFindData(&s, 2);
  PrintSList(&s);
  
  // 移除鏈表中第一個值爲data的元素 
  SListRemove(&s, 0);
  PrintSList(&s);
  // 移除鏈表中所有值爲data的元素
  //SListRemoveAll(&s, 1);
  //PrintSList(&s);
  
  // 獲取鏈表有效元素個數 
  SListSize(&s);//
  PrintSList(&s);
  
  // 檢測鏈表是否爲空
  SListEmpty(&s);
  PrintSList(&s);
  
  //獲取鏈表中的第一個元素
  SListFront(&s);
  PrintSList(&s);
  
  //獲取鏈表中的第一個元素
  SListBack(&s);
  PrintSList(&s);
  
  //銷燬鏈表
  SListDestory(&s);
  PrintSList(&s);
 system("pause");
 return 0; 
}

運行結果如下:在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章