這是”我爲開源造垃圾系列“的第一篇博文,以後會不定期更新此係列文章。。。望能造點精華出來。。。
衆所周知,數據結構的線性表在擼碼生涯的運用是很平常的,也是非常簡單,最最基礎的一個數據結構了。其中單鏈表又是一個非常重要的一塊。首先講一下單鏈表!
廢話不說,先請出度娘。
這個度娘比較囉嗦,我簡單上個圖解釋一下。科科。(其實還是度娘那裏來的)
其實簡單來講,單鏈表就是一個 開了bug功能 自帶指針的一個數據複合結構,他有一個頭節點和一個尾節點,爲節點指向NULL
單鏈表具體涉及的操作有很多種,這邊稍微羅列幾種:
以下是關於線性錶鏈接存儲(單鏈表)操作的18種算法 */ /* 1.初始化線性表,即置單鏈表的表頭指針爲空 */ /* 2.創建線性表,此函數輸入負數終止讀取數據*/ /* 3.打印鏈表,鏈表的遍歷*/ /* 4.清除線性表L中的所有元素,即釋放單鏈表L中所有的結點,使之成爲一個空表 */ /* 5.返回單鏈表的長度 */ /* 6.檢查單鏈表是否爲空,若爲空則返回1,否則返回0 */ /* 7.返回單鏈表中第pos個結點中的元素,若pos超出範圍,則停止程序運行 */ /* 8.從單鏈表中查找具有給定值x的第一個元素,若查找成功則返回該結點data域的存儲地址,否則返回NULL */ /* 9.把單鏈表中第pos個結點的值修改爲x的值,若修改成功返回1,否則返回0 */ /* 10.向單鏈表的表頭插入一個元素 */ /* 11.向單鏈表的末尾添加一個元素 */ /* 12.向單鏈表中第pos個結點位置插入元素爲x的結點,若插入成功返回1,否則返回0 */ /* 13.向有序單鏈表中插入元素x結點,使得插入後仍然有序 */ /* 14.從單鏈表中刪除表頭結點,並把該結點的值返回,若刪除失敗則停止程序運行 */ /* 15.從單鏈表中刪除表尾結點並返回它的值,若刪除失敗則停止程序運行 */ /* 16.從單鏈表中刪除第pos個結點並返回它的值,若刪除失敗則停止程序運行 */ /* 17.從單鏈表中刪除值爲x的第一個結點,若刪除成功則返回1,否則返回0 */ /* 18.交換2個元素的位置 */ /* 19.將線性表進行快速排序 */
當然,除了這些,還是有很多變體,可以根據自己的需求編寫。
而話不多說,上段代碼先:(我這邊只實現了其中一部分的功能,不過寫起來已經很長了,具體的內容可以看代碼的註釋)
//
// Header.h
// danlianbiao
//
// Created by mouweng on 17/3/18.
// Copyright © 2017年 單鏈表. All rights reserved.
//
#include<iostream>
using namespace std;
#ifndef Header_h
#define Header_h
class Node//定義一個叫節點的類,是單鏈表的基本元素!
{
public:
int data;
Node *next;
void printNode()//用於打印節點
{
cout<<data<<endl;
};
};
class List
{
public:
List();//構造函數,用於初始化單鏈表
~List();//析構函數
void ClearList();//清空列表,和析構函數最大的區別是不去除頭結點
bool ListEmpty();//判斷單鏈表是否爲空
int ListLength();//返回單鏈表的長度
bool GetElem(int i,Node *pNode);//得到第i個位置的元素
int LocateElem(Node *pNode);//取得*pNode的值所在的節點的位置
bool PriorElem(Node *pCurrentNode,Node *pPreNode);//取得前一個節點的數據
bool NextElem(Node *pCurrentNode,Node *pNextNode);//取得後一個節點的數據
void ListTraverse();//遍歷這個節點
bool ListInsert(int i,Node *pNode);//插入元素
bool ListDelete(int i,Node *pNode);//刪除元素
bool ListInsertHead(Node *pNode);//在頭部插入函數
bool ListInsertTail(Node *pNode);//在尾部插入函數
private:
Node *m_pList;
int m_iLength;//用於儲存單鏈表的長度
};
#endif /* Header_h */
以上爲頭文件部分,用於定義單鏈表類
//
// main.cpp
// danlianbiao
//
// Created by mouweng on 17/3/18.
// Copyright © 2017年 單鏈表. All rights reserved.
//
#include <iostream>
#include "Header.h"
List::List()
{
m_pList = new Node;
m_pList->data=0;
m_pList->next=NULL;
m_iLength = 0;
}
bool List::ListEmpty()
{
if(m_iLength==0)
return true;
else
return false;
}
int List::ListLength()
{
return m_iLength;
}
void List::ClearList()
{
Node *currentNode=m_pList->next;
while(currentNode!=NULL)
{
Node *temp =currentNode->next;
delete currentNode;
currentNode = temp;
}
m_pList->next=NULL;
}
List::~List()
{
ClearList();
delete m_pList;
m_pList=NULL;
}
bool List::ListInsertHead(Node *pNode)
{
Node *temp=m_pList->next;
Node *newNode=new Node;
if(newNode==NULL)//申請內存失敗,返回0;
return false;
newNode->data=pNode->data;
m_pList->next = newNode;
newNode->next=temp;
m_iLength++;
return true;
}
bool List::ListInsertTail(Node *pNode)
{
Node *currentNode=m_pList;
while(currentNode->next!=NULL)
currentNode=currentNode->next;
Node *newNode=new Node;
if(newNode==NULL)//申請內存失敗,返回0;
return false;
newNode->data=pNode->data;
newNode->next=NULL;
currentNode->next=newNode;
m_iLength++;
return true;
}
bool List::ListInsert(int i,Node *pNode)
{
if(i<0||i>m_iLength)
return false;
Node *currentNode=m_pList;
for(int k=0;k<i;k++)//到i的前一個位置
currentNode=currentNode->next;
Node *newNode=new Node;
if(newNode==NULL)//申請內存失敗,返回0;
return false;
newNode->data=pNode->data;
newNode->next=currentNode->next;
currentNode->next=newNode;
m_iLength++;
return true;
}
bool List::ListDelete(int i,Node *pNode)
{
if(i<0||i>=m_iLength)//這裏和Insert有區別,因爲尾節點是不能刪除的!
return false;
Node *currentNode=m_pList;
Node *currentNodeBefore=NULL;//這樣他就擁有一個自己的地址了!
for(int k=0;k<=i;k++)
{
currentNodeBefore=currentNode;
currentNode=currentNode->next;
}
currentNodeBefore->next = currentNode->next;
pNode->data=currentNode->data;
delete currentNode;
currentNode=NULL;
m_iLength--;
return true;
}
bool List::GetElem(int i,Node *pNode)
{
if(i<0||i>m_iLength)
return false;
Node *currentNode=m_pList;
for(int k=0;k<i;k++)//到i的前一個位置
currentNode=currentNode->next;
pNode->data=currentNode->data;
return true;
}
int List::LocateElem(Node *pNode)//返回第一個相同的位置
{
Node *currentNode=m_pList;
int count=0;//用於計數
while(currentNode!=NULL)
{
currentNode=currentNode->next;
if(currentNode->data==pNode->data)
{
return count;
}
count++;
}
return -1;
}
bool List::PriorElem(Node *pCurrentNode,Node *pPreNode)
{
Node *currentNode=m_pList;
Node *tempNode=NULL;
while(currentNode->next!=NULL)
{
tempNode=currentNode;
currentNode=currentNode->next;
if(currentNode->data==pCurrentNode->data)
{
if(tempNode==m_pList)//如果已經是第一個節點,就沒有更前的節點了
return false;
pPreNode->data=tempNode->data;
return true;
}
}
return false;
}
bool List::NextElem(Node *pCurrentNode,Node *pNextNode)
{
Node *currentNode=m_pList;
while(currentNode!=NULL)
{
currentNode=currentNode->next;
if(currentNode->data==pCurrentNode->data)
{
if(currentNode->next==NULL)//如果已經是第一個節點,就沒有更前的節點了
return false;
pNextNode->data=currentNode->next->data;
return true;
}
}
return false;
}
void List::ListTraverse()//遍歷函數
{
Node *currentNode=m_pList;
while(currentNode->next!=NULL)
{
currentNode=currentNode->next;
currentNode->printNode();
}
}
int main()
{
Node node1;
node1.data=3;
Node node2;
node2.data=4;
Node node3;
node3.data=5;
Node node4;
node4.data=6;
Node node5;
node5.data=7;
Node temp;
List *pList=new List();
/*pList->ListInsertHead(&node1);
pList->ListInsertHead(&node2);
pList->ListInsertHead(&node3);
pList->ListInsertHead(&node4);
pList->ListTraverse();*/
pList->ListInsertTail(&node1);
pList->ListInsertTail(&node2);
pList->ListInsertTail(&node3);
pList->ListInsertTail(&node4);
pList->ListInsert(1, &node5);
pList->ListDelete(1,&temp);
pList->ListTraverse();
cout<<"temp = "<<temp.data<<endl;
delete pList;
pList=NULL;
}