普通單向鏈表應該包含的數據和方法:
結點類(Node):
屬性:
AnyType value; //任意類型的數據
Node* next; //指向下一個節點的指針
方法:
構造方法 Node(AnyType* value, Node* next);
鏈表類(LinkedList):
Node* head; //鏈表頭結點的指針
Node* tail; //鏈表尾結點的指針,可選
int length; //鏈表長度,可選
int isEmpty(); //鏈表是否爲空
int contains(); //鏈表是否包含某個值
void addToHead(AnyType value); //向鏈表頭添加數據
void addToTail(AnyType value); //向鏈表尾添加數據
void addNode(AnyType value, int index) //向鏈表指定下標處添加數據
int deleteFromHead(); //從鏈表頭刪除一個數據,返回被刪除的數據
int deleteFromTail(); //從鏈表尾刪除一個數據,返回被刪除的數據
int deleteNode(); //刪除指定下標處的數據,返回被刪除的數據
實現每種方法的思路:
1、因爲LinkedList類的屬性有:head,tail,length
所以要根據不同情況更新三個屬性
2、所以每種方法,都要處理:
1)head發生變化
2)tail發生變化
的情況
下方是C++代碼,有詳細註釋:
#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
//節點類,代表鏈表的結點
class Node{
public:
int value; //存儲節點的值
Node* next; //存儲下一個節點的指針
Node(int aValue, Node* aNext = NULL){ //構造函數,必須傳入結點的值,下一個節點默認爲NULL
this->value = aValue;
this->next = aNext;
}
};
class LinkedList{ //普通單向鏈表類
public:
int length = 0; //鏈表長度,該屬性不重要,下面的方法中也沒有用到,但是維護了該屬性
Node* head = 0; //鏈表頭節點的指針
Node* tail = 0; //鏈表尾節點的指針
LinkedList(){
}
int isEmpty(){ //判斷鏈表是否爲空,頭指針爲0代表空
return head == 0;
}
//向鏈表頭添加數據
int addToHead(int aValue){
head = new Node(aValue, head); //添加節點
if (tail == 0) tail = head; //如果尾指針爲空,說明鏈表本身爲空,更新尾指針
length++;
}
//向鏈表尾添加數據
int addToTail(int aValue){
//如果尾指針爲空,說明鏈表本身爲空,更新尾指針和頭指針
if (tail == 0) head = tail = new Node(aValue);
//否則只更新尾指針
else tail = tail->next = new Node(aValue);
length++;
}
//從鏈表頭刪除數據
int deleteFromHead(){
//如果鏈表爲空,無法刪除,返回-1
if (head == 0) return -1;
//記錄被刪除的結點指針和值
Node* deletedNode = head;
int deletedValue = head->value;
if (head == tail) //如果鏈表只有一個結點,那麼刪除後頭和尾都爲空
head = tail = 0;
else
head = head->next;
length--;
delete deletedNode;
return deletedValue; //返回被刪除的值
}
int deleteFromTail(){
//如果鏈表爲空,無法刪除,返回-1
if (head == 0) return -1;
//記錄被刪除的結點指針和值
Node* deletedNode = tail;
int deletedValue = tail->value;
if (head == tail) //如果鏈表只有一個結點,那麼刪除後頭和尾都爲空
head = tail = 0;
else {
Node* now = 0;
for(now=head; now->next!=tail; now=now->next); //遍歷鏈表,找到倒數第二個結點
//printf("Fine -2 Node Value: %d\n", now->value);
now->next = 0;
tail = now;
}
length--;
delete deletedNode;
return deletedValue; //返回被刪除的值
}
int deleteNode(int index){
if (index <= 0) return -1;
//如果鏈表爲空,無法刪除,返回-1
if (head == 0) return -1;
Node* now = 0;
int cnt = 1; //計數器
/*
下面的循環作用:
情況1:正常情況下,找到要刪除的結點的前一個結點;
情況2:如果要刪除的結點序號大於總結點數,使得找到的值停止在NULL
*/
for(now=head; cnt+1<index && now!=0; cnt++,now=now->next);
//printf("Find now: value: %d\n", now->value);
if(now == 0) return -1; //情況2發生,直接返回
//記錄被刪除的結點指針和值
Node* deletedNode = now->next;
int deletedValue = deletedNode->value;
//情況1:將該結點刪除
if (cnt == index-1)
now->next = now->next->next;
length--;
//如果末尾結點被刪除,更新tail
if (deletedNode->next == 0){
tail = now;
}
delete deletedNode;
return deletedValue;
}
//向指定序號處插入結點
void addNode(int value, int index){ //index starts from 1
if (index <= 0) return;
//處理鏈表爲空插入結點的情況
if (head == 0 && index == 1) {
head = tail = new Node(value);
length++;
return ;
}
//處理在鏈表頭插入數據的情況
if (index == 1){
head = new Node(value, head);
length++;
return ;
}
Node* aheadOfAdd = NULL;
int cnt = 1;
//循環找到要插入的結點之前的那個結點
for (aheadOfAdd=head,cnt=1; aheadOfAdd!=0&&cnt+1<index; cnt++,aheadOfAdd=aheadOfAdd->next);
//如果以上循環因爲條件“cnt+1<index”不成立而終止,則因爲要插入的結點序號超過了鏈表總大小
if (!index == cnt+1)
return ;
if (aheadOfAdd == 0)
return ;
//printf("%d\n", aheadOfAdd->value);
aheadOfAdd->next = new Node(value, aheadOfAdd->next);
length++;
//如果向尾部插入了結點,更新tail
if (aheadOfAdd->next->next == 0) tail = aheadOfAdd->next;
}
void printSelf(){ //打印鏈表內容
Node* nodeToPrint = this->head;
printf("Content of LinkedList:");
while(nodeToPrint != NULL){
printf("%d ", nodeToPrint->value);
if(nodeToPrint == tail)
printf("tail is reached!\n");
nodeToPrint = nodeToPrint->next;
}
printf("\n");
}
//判斷鏈表是否包含某個值
bool contains(int value){
for(Node* now=head; now!=0; now=now->next)
if (now->value == value)
return true;
return false;
}
};
//測試程序
int main(){
LinkedList* list = new LinkedList();printf(" %d\n", list->length);
list->addToHead(1);list->printSelf();printf(" %d\n", list->length);
list->addToHead(2);list->printSelf();printf(" %d\n", list->length);
list->addToHead(3);list->printSelf();printf(" %d\n", list->length);
list->addToHead(4);list->printSelf();printf(" %d\n", list->length);
list->addToTail(100);list->printSelf();printf(" %d\n", list->length);
list->addToTail(101);list->printSelf();printf(" %d\n", list->length);
list->addToTail(102);list->printSelf();printf(" %d\n", list->length);
list->addToTail(103);list->printSelf();printf(" %d\n", list->length);
list->deleteNode(8);list->printSelf();printf(" %d\n", list->length);
printf("%d",list->contains(103));
}