单向链表操作(C++实现)

单向链表操作,某司笔试题答案:

project1为链表新建,增、删节点,逆转等常规操作;

project2为链表数字指定和插入+,-或空格;

project3为聚类。

#include 
#include 
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> result;
vector data_0;
data_0.push_back(data[0]);
result.push_back(data_0);
int flag = 0;
vector 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 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;
}
 

你可能感兴趣的:(C++)