資料結構與演算法筆記(三)反轉部分連結串列
阿新 • • 發佈:2018-12-11
反轉部分連結串列
上次我們搞定了反轉單向連結串列和雙向連結串列的問題,但實際過程中我們可能只要反轉部分連結串列,在這種情況下我們需要對上次寫出的類增加一個叫做reverse_part_linklist的函式,傳入引數為兩個整數from和to,將from到to之間的節點進行反轉
反轉部分單向連結串列
函式的設計思路主要有3點:
1.判斷傳入的引數是否滿足1
≤
from
≤
to
≤
N,若不滿足直接返回。
2.正如上篇部落格所講對連結串列進行插入刪除必須要找到其相鄰的節點,因此我們要找到第from-1個節點fPre和第to+1個節點tPos。
3.在對連結串列處理時要時刻關注是否包含頭節點,如果fPre為null那麼我們要反轉的部分包含頭節點,那麼我們要將頭節點賦為未反轉前反轉部分的最後一個節點;如果fPre不為null,則head保持不變。
#include <iostream>
using namespace std;
struct node {
int data;
node * next;
};
class linklist {
private:
node * head;
public:
linklist() {
head = NULL; // 初始化head
}
void add(int d) {
node *temp = head;
node * newnode = new node();
newnode->next = NULL;
newnode->data = d;
if (temp == NULL) {
head = newnode; // 對空連結串列的處理
return;
}
while (temp->next != NULL) {
temp = temp->next; // 走到連結串列最後一個非空節點
}
temp->next = newnode;
}
void print() {
node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
void reverse() {
node* pre = NULL; // 新連結串列的頭結點
node* next = NULL; // 儲存原連結串列要處理的下一個節點,防止丟失
while (head != NULL) {
next = head->next;
head->next = pre;
pre = head;
head = next;
}
head = pre;
}
void reverse_part(int from, int to) {
int len = 0; // 連結串列的長度
if (from > to || from < 1) {
return; // 判斷條件1
}
node* tempnode = head;
node* fPre = NULL;
node* tPos = NULL;
while (tempnode != NULL) {
len++;
fPre = len == from-1 ? tempnode : fPre; // 如果到了from-1,則將當前節點賦給fPre
tPos = len == to+1 ? tempnode : tPos; // 如果到了to+1, 則將當前節點賦給tPos
tempnode = tempnode->next;
}
if (to > len) {
return ; // 判斷條件2
}
tempnode = fPre == NULL ? head : fPre->next;
node * tempnode2 = tempnode->next;
tempnode->next = tPos;
node * next = NULL;
while (tempnode2 != tPos) {
next = tempnode2->next;
tempnode2->next = tempnode;
tempnode = tempnode2;
tempnode2 = next; // 這裡與反轉連結串列寫法類似
}
if (fPre != NULL) {
fPre->next = tempnode;
return ;
}
head = tempnode;
}
};
int main() {
linklist l;
int cnt;
cin >> cnt;
for (int i = 0; i < cnt; i++) {
l.add(i);
}
l.print();
l.reverse_part(1,3);
l.print();
return 0;
}