單向鏈表操作(C++實現)

單向鏈表操作,某司筆試題答案:

project1爲鏈表新建,增、刪節點,逆轉等常規操作;

project2爲鏈表數字指定和插入+,-或空格;

project3爲聚類。

#include <iostream>
#include <vector>
using namespace std;

/*  Project 1

 定義一個單向鏈表node, 每個節點值爲int.
 定義函數void create_linklist(…, int n)來生成鏈表,鏈表長度由參數n傳入,生成的鏈表要作爲參數返回,而不是當初函數返回值返回,鏈表節點值爲1,2,3...n。
 定義函數reverse_linklist(...), 對參數傳入的鏈表進行逆轉。
 定義函數insert_node(node *pHead, int Index, int Value ), 在指定鏈表位置Index插入指定Value
 定義函數delete_node(node *pHead,  int Index),刪除鏈表位置Index所在的節點
 定義函數delete_linklist(), 刪除整個鏈表


 main()函數:
 1.調用create_linklist()生成鏈表
 2.調用insert_node()插入節點
 3.調用delete_node()刪除節點
 4.調用reverse_linklist()逆轉
 5.打印鏈表所有值
 6.結束程序工作
 */

struct node {
int v;
node* n;
};

/* 鏈表長度由參數n傳入,生成的鏈表要作爲參數返回,而不是當初函數返回值返回,
 鏈表節點值爲1,2,3...n
 */
void create_linklist(node **pHead, int n) {
node *pEnd = nullptr;
//循環創建鏈表
for (int i = 1; i <= n; i++) {
node *temp = (node*) malloc(sizeof(node)); //在堆區分配空間創建變量
temp->v = i; //賦值
temp->n = NULL;
if (NULL == *pHead) {
*pHead = temp;
pEnd = temp;
} else {
pEnd->n = temp;
pEnd = temp;
}
}
return;
}

//對參數傳入的鏈表進行逆轉
void reverse_linklist(node **pHead) {

if (NULL == *pHead) {
return;
}
node *pNode;
pNode = *pHead;
node *Prev = NULL;
node *pNext = NULL;
while (NULL != pNode) {
pNext = pNode->n;
if (NULL == pNext) {
*pHead = pNode;
}
pNode->n = Prev;
Prev = pNode;
pNode = pNext;
}
return;
}

//在指定鏈表位置Index插入指定Value
// Index 爲 1 ~ n 代表 1 ~ n 個節點
// Index = 0 即爲頭添加
void insert_node(node **pHead, int Index, int Value) {
if (Index < 0) {
return;
}
node *newNode; // 新節點的指針
node *previous; // 當前指針的前一個指針
node *current; // 當前指針

current = *pHead; // 初始化
previous = NULL;

int insert = 0;
// 查找插入的位置
while (NULL != current && insert < Index) {
previous = current;
current = current->n;
insert++;
}
// 給新節點分配空間
newNode = (node *) malloc(sizeof(node));
if (NULL == newNode) {
std::cout << "分配空間失敗" << std::endl;
return;
}
newNode->v = Value;
// 更改新節點的前驅和後繼節點
newNode->n = current;
if (NULL == previous) // 此時插入節點的爲鏈表中第一個節點,修改頭指針
*pHead = newNode;
else
previous->n = newNode;
return;
}

//刪除鏈表位置Index所在的節點
void delete_node(node **pHead, int Index) {
if (Index < 0) {
return;
}
node *p, *q;
p = *pHead;
//判斷空表
if (NULL == pHead) {
std::cout << "該鏈表是空鏈表,不能進行結點刪除!" << std::endl;
return;
}
int delete_num = 1;
//先找到要刪除的結點
while (Index != delete_num && NULL != p->n) //p指向的不是所要找的結點且後面還有結點
{
q = p;  //q用來記錄p前一個結點
p = p->n;
delete_num++;
}         //p後移一個結點
if (Index == delete_num) {
if (0 == Index)  //如果要刪除的是頭結點
*pHead = p->n;
else
q->n = p->n;    //否則將下一結點地址賦給前一結點地址
return;
} else
std::cout << "Index: " << Index << "大於鏈表長度,在鏈表中沒有找到" << std::endl;     //找不到該結點
return;
}

//刪除整個鏈表
void delete_linklist(node **pHead) {

node *q = NULL;
node *p;
p = *pHead;
while (p) {
q = p->n;
free(p);
p = q;
}
}

/* Project 2
 編寫一個函數int Calculate(node *pHead, int k);在鏈表數字之間插入+ 、- 或者什麼都不插入,使得計算結果等於
 給定的整數 K,返回所有可能性的個數。例如鏈表有數字 1, 2, 3, ..., 9 並且給
 定的整數爲 100,那麼其中的一種可能性是: 1 + 2 + 34 – 5 + 67 – 8 + 9 = 100。
 (不允許開闢額外的字符串空間,假設鏈表所有數字都大於 0 並且小於 10)
 */
int sum = 0;

void CalculateValue(node *pHead, int target, int curValue) {
if (pHead == nullptr && curValue == target) {
sum++;
return;
}
int admin = 0;
for (node *nd = pHead; nd != nullptr; nd = nd->n)     //遍歷以node開頭的鏈表,
{
admin = admin * 10 + nd->v;     //每個節點的值進行計算,使得進行數字不同組合
CalculateValue(nd->n, target, curValue + admin);
CalculateValue(nd->n, target, curValue - admin);
}
}

int Calculate(node *pHead, int k) {
sum = 0;
CalculateValue(pHead, k, 0);
return sum;
}

/*  Project 3

 定義一個聚類函數 cluster(int data[], int len, int radius);
 data中的值沒有重複,長度爲len,
 把按照數值的聚類進行分爲n組,
 對於組G中任意一個數值a,總是能在本組G中找到一個數值b, 使 |a-b| < radius  .
 在函數內部打印出所有n個組成員,分成n行輸出

 (要求:不能使用數組排序操作)

 例如:
 輸入 data[] = { 1, 20, 89, 22, 72, 2,39, 3,56,86, 5, 93,13, 15, 18, 73, 79, 81, 25, 38, 43, 83,48, 52, 59,92,84,95,87 };
 正確的屏幕輸出爲組及成員爲(每行爲一組,行之間順序隨意,組內成員順序隨意):
 1, 2, 3, 5,
 13, 15, 18, 20, 22, 25,
 39, 38, 43, 48, 52, 56, 59,
 73, 72,
 79, 89, 92, 84, 95,87,86, 93,81, 83,

 */
/*==========Project3=================|43-48| = radius
 1,2,3,5,
 20,22,18,13,15,25,
 89,86,93,83,79,81,92,84,95,87,
 72,73,
 39,38,43,
 56,52,48,59,*/
void cluster(int data[], int len, int radius) {
std::vector<vector<int>> result;
vector<int> data_0;
data_0.push_back(data[0]);
result.push_back(data_0);
int flag = 0;
vector<int> row;
//遍歷一遍數組
for (int i = 1; i < len; i++) {
flag = 0;
for (int j = 0; j < result.size(); j++) {
for (int k = 0; k < result[j].size(); k++) {
if (abs(result[j][k] - data[i]) < radius) {
if (0 == flag) {
result[j].push_back(data[i]);
}
if (row.size() > 0) {
int row_flag = 0;
for (int m = 0; m < row.size(); m++) {
if (j == row[m])
row_flag = 1;
}
if (0 == row_flag) {
row.push_back(j);
flag++;
}
} else {
row.push_back(j);
flag++;
}

}
}
}
//聚合行
if (row.size() > 1) {
for (int row_num = 1; row_num < row.size(); row_num++) {
for (int m = 0; m < result[row[row_num]].size(); m++) {
result[row[0]].insert(result[row[0]].end(),
result[row[row_num]].begin(),
result[row[row_num]].end());
result[row[row_num]].clear();
}
}

}
row.clear();
if (0 == flag) {
vector<int> data_i;
data_i.push_back(data[i]);
result.push_back(data_i);
}

}
//輸出
for (int i = 0; i < result.size(); i++) {
if (result[i].size() > 0) {
for (int j = 0; j < result[i].size(); j++) {
std::cout << result[i][j] << ",";
}
std::cout << endl;
}
}
}

int main() {
// Project 1
// 可將頭尾指針及節點個數封裝結構體,更方便操作
cout << "==========Project1=================" << endl;
node *pHead = nullptr;
// 1.調用create_linklist()生成鏈表
create_linklist(&pHead, 9);
// 2.調用insert_node()插入節點
insert_node(&pHead, 9, 10);
// 3.調用delete_node()刪除節點
delete_node(&pHead, 10);
// 4.調用reverse_linklist()逆轉
reverse_linklist(&pHead);

node *pTemp = pHead;
while (pTemp) {
std::cout << pTemp->v << " ";
pTemp = pTemp->n;
}
cout << endl;
cout << "==========Project1=================" << endl;
cout << endl;

// Project 2
cout << "==========Project2=================" << endl;
delete_linklist(&pHead);
pHead = nullptr;
create_linklist(&pHead, 9);
cout << Calculate(pHead, 100) << endl;
cout << "==========Project2=================" << endl;
cout << endl;

// Project 3
cout << "==========Project3=================" << endl;
int data[] = { 1, 20, 89, 22, 72, 2, 39, 3, 56, 86, 5, 93, 13, 15, 18, 73,
79, 81, 25, 38, 43, 83, 48, 52, 59, 92, 84, 95, 87 };
cluster(data, sizeof(data) / sizeof(int), 5);
/*
 正確的輸出爲組及成員爲(組內成員順序隨意):
 1, 2, 3, 5,
 13, 15, 18, 20, 22, 25,
 39, 38, 43, 48, 52, 56, 59,
 73, 72,
 79, 89, 92, 84, 95,87,86, 93,81, 83,
 */
cout << "==========Project3=================" << endl;

return 0;
}
 

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