C链表:将数字放在列表前面,并使所有数字移位
我正在试着让这个方法开始工作。我想在列表中插入一个数字,使最后一个数字消失。如果这是列表p1->2->3->4->5,那么在shiftInsert8之后,列表需要看起来像p8->1->2->3->4。正如你所见,最后一个数字需要消失。我如何实现这一点C链表:将数字放在列表前面,并使所有数字移位,c,linked-list,C,Linked List,我正在试着让这个方法开始工作。我想在列表中插入一个数字,使最后一个数字消失。如果这是列表p1->2->3->4->5,那么在shiftInsert8之后,列表需要看起来像p8->1->2->3->4。正如你所见,最后一个数字需要消失。我如何实现这一点 #include <stdio.h> #include <stdlib.h> struct elem { int value; struct elem *next; }; typedef struct e
#include <stdio.h>
#include <stdlib.h>
struct elem {
int value;
struct elem *next;
};
typedef struct elem Node;
Node *root;
Node * addElem(Node *p, int value) {
p->next = malloc(sizeof *p);
p = p->next;
p->value = value;
p->next = NULL;
return p;
}
void shiftInsert(Node *n, int v) {
int tmp;
while (n != NULL) {
Node * new_node;
new_node = malloc(sizeof (new_node));
n = n->next;
}
}
void printList() {
Node *p = root;
while (p != NULL) {
printf("%2d -> ", p->value);
p = p->next;
}
printf("NULL\n");
}
int main(int argc, char **argv) {
Node *p;
int i = 0;
root = p = malloc(sizeof (Node));
p->value = 1;
for (i = 2; i <= 10; i++) {
p = addElem(p, i);
}
printList();
shiftInsert(root, 88);
printList();
shiftInsert(root->next->next->next, 33);
printList();
return 0;
}
根据您的示例,您希望插入第一个位置并删除最后一个位置。因此,基本上您希望创建一个新根,然后找到最后一个元素,并将其next设置为NULL 首先是delete函数:
void deleteLast()
{
int i, before_last = 0;
Node *temp;
/* Find last element to remove it*/
temp = root;
for(i = 0; temp->next != NULL; i++) { // "i" will be the index of the last element
temp = temp->next;
}
before_last = i - 1; // the one before "i" will be the new last element
temp = root;
for(i = 0; i < before_last; i++) { // find the one before last and set its "next" NULL
temp = temp->next;
}
free(temp->next);
temp->next = NULL;
}
根据main,要在某个元素之后插入,必须首先找到它。然后创建一个新元素,并将其下一个设置为原始元素的下一个,这样就不会丢失列表的其余部分。最后,将原始元素的下一个元素设置为新元素
void shiftInsertAnywhere(Node *position, int v) {
int i;
Node *temp;
temp = root;
for(i = 0; temp->value != position->value; i++) {
temp = temp->next;
}
if (temp != NULL) {
Node * new_root;
/* Create new root */
new_root = malloc(sizeof (new_root));
new_root->next = temp->next; // save the rest of the list
new_root->value = v; // set new value
position->next = new_root; // insert the new element after "position" element
deleteLast();
}
}
这将在位置后插入
例如:
printList();
shiftInsertRoot(88);
printList();
shiftInsertRoot(33);
printList();
shiftInsertAnywhere(root->next->next, 99);
printList();
shiftInsertAnywhere(root, 17171);
printList();
输出:
根据您的示例,您希望插入第一个位置并删除最后一个位置。因此,基本上您希望创建一个新根,然后找到最后一个元素,并将其next设置为NULL 首先是delete函数:
void deleteLast()
{
int i, before_last = 0;
Node *temp;
/* Find last element to remove it*/
temp = root;
for(i = 0; temp->next != NULL; i++) { // "i" will be the index of the last element
temp = temp->next;
}
before_last = i - 1; // the one before "i" will be the new last element
temp = root;
for(i = 0; i < before_last; i++) { // find the one before last and set its "next" NULL
temp = temp->next;
}
free(temp->next);
temp->next = NULL;
}
根据main,要在某个元素之后插入,必须首先找到它。然后创建一个新元素,并将其下一个设置为原始元素的下一个,这样就不会丢失列表的其余部分。最后,将原始元素的下一个元素设置为新元素
void shiftInsertAnywhere(Node *position, int v) {
int i;
Node *temp;
temp = root;
for(i = 0; temp->value != position->value; i++) {
temp = temp->next;
}
if (temp != NULL) {
Node * new_root;
/* Create new root */
new_root = malloc(sizeof (new_root));
new_root->next = temp->next; // save the rest of the list
new_root->value = v; // set new value
position->next = new_root; // insert the new element after "position" element
deleteLast();
}
}
这将在位置后插入
例如:
printList();
shiftInsertRoot(88);
printList();
shiftInsertRoot(33);
printList();
shiftInsertAnywhere(root->next->next, 99);
printList();
shiftInsertAnywhere(root, 17171);
printList();
输出:
在不增加列表的情况下,不需要为插入节点分配新空间。下面是一个函数,它在列表的开头插入一个节点,并删除最后一个节点:
Node * shiftInsert(Node *n, int v) {
Node *tail = n;
if (n == NULL){
return n;
} else if (n->next == NULL) {
n->value = v;
return n;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
n = tail->next;
tail->next = NULL;
return n;
}
Node * shiftInsertAny(Node *root, Node *n, int v) {
Node *tail = n;
Node *insert = root;
if (root == NULL){
return root;
} else if (root->next == NULL) {
root->value = v;
return root;
}
while (n != root && insert->next != n)
insert = insert->next;
if (insert->next->next == NULL) {
insert->next->value = v;
return root;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
if (insert == root)
root = tail->next;
else
insert->next = tail->next;
tail->next = NULL;
return root;
}
注意,这个版本的shiftInsert返回一个指向列表头部的指针
下面是第二个函数,它允许您在列表中的任何位置插入节点,并删除最后一个节点:
Node * shiftInsert(Node *n, int v) {
Node *tail = n;
if (n == NULL){
return n;
} else if (n->next == NULL) {
n->value = v;
return n;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
n = tail->next;
tail->next = NULL;
return n;
}
Node * shiftInsertAny(Node *root, Node *n, int v) {
Node *tail = n;
Node *insert = root;
if (root == NULL){
return root;
} else if (root->next == NULL) {
root->value = v;
return root;
}
while (n != root && insert->next != n)
insert = insert->next;
if (insert->next->next == NULL) {
insert->next->value = v;
return root;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
if (insert == root)
root = tail->next;
else
insert->next = tail->next;
tail->next = NULL;
return root;
}
此函数还返回指向列表头的指针,并将指向列表头的指针和指向插入点的指针作为参数。新节点插入到由指针n指示的节点前面
如果在代码中这样调用这些函数:
printList();
root = shiftInsert(root, 88);
printList();
root = shiftInsertAny(root, root->next->next->next, 33);
printList();
这是输出:
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> NULL
88 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
88 -> 1 -> 2 -> 33 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> NULL
我更新了shiftInsertAny函数的上述代码段。我做了一个更改,允许它在列表的开头插入一个节点,但是我忘记了在前面编辑代码段。使用此函数,可以插入到第一个节点或最后一个节点中。例如,使用5元素列表,可以执行以下操作:
printList();
root = shiftInsertAny(root, root, 88);
printList();
root = shiftInsertAny(root, root->next->next->next->next, 33);
printList();
其输出:
1 -> 2 -> 3 -> 4 -> 5 -> NULL
88 -> 1 -> 2 -> 3 -> 4 -> NULL
88 -> 1 -> 2 -> 3 -> 33 -> NULL
在不增加列表的情况下,不需要为插入节点分配新空间。下面是一个函数,它在列表的开头插入一个节点,并删除最后一个节点:
Node * shiftInsert(Node *n, int v) {
Node *tail = n;
if (n == NULL){
return n;
} else if (n->next == NULL) {
n->value = v;
return n;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
n = tail->next;
tail->next = NULL;
return n;
}
Node * shiftInsertAny(Node *root, Node *n, int v) {
Node *tail = n;
Node *insert = root;
if (root == NULL){
return root;
} else if (root->next == NULL) {
root->value = v;
return root;
}
while (n != root && insert->next != n)
insert = insert->next;
if (insert->next->next == NULL) {
insert->next->value = v;
return root;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
if (insert == root)
root = tail->next;
else
insert->next = tail->next;
tail->next = NULL;
return root;
}
注意,这个版本的shiftInsert返回一个指向列表头部的指针
下面是第二个函数,它允许您在列表中的任何位置插入节点,并删除最后一个节点:
Node * shiftInsert(Node *n, int v) {
Node *tail = n;
if (n == NULL){
return n;
} else if (n->next == NULL) {
n->value = v;
return n;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
n = tail->next;
tail->next = NULL;
return n;
}
Node * shiftInsertAny(Node *root, Node *n, int v) {
Node *tail = n;
Node *insert = root;
if (root == NULL){
return root;
} else if (root->next == NULL) {
root->value = v;
return root;
}
while (n != root && insert->next != n)
insert = insert->next;
if (insert->next->next == NULL) {
insert->next->value = v;
return root;
}
while (tail->next->next != NULL)
tail = tail->next;
tail->next->value = v;
tail->next->next = n;
if (insert == root)
root = tail->next;
else
insert->next = tail->next;
tail->next = NULL;
return root;
}
此函数还返回指向列表头的指针,并将指向列表头的指针和指向插入点的指针作为参数。新节点插入到由指针n指示的节点前面
如果在代码中这样调用这些函数:
printList();
root = shiftInsert(root, 88);
printList();
root = shiftInsertAny(root, root->next->next->next, 33);
printList();
这是输出:
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> NULL
88 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
88 -> 1 -> 2 -> 33 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> NULL
我更新了shiftInsertAny函数的上述代码段。我做了一个更改,允许它在列表的开头插入一个节点,但是我忘记了在前面编辑代码段。使用此函数,可以插入到第一个节点或最后一个节点中。例如,使用5元素列表,可以执行以下操作:
printList();
root = shiftInsertAny(root, root, 88);
printList();
root = shiftInsertAny(root, root->next->next->next->next, 33);
printList();
其输出:
1 -> 2 -> 3 -> 4 -> 5 -> NULL
88 -> 1 -> 2 -> 3 -> 4 -> NULL
88 -> 1 -> 2 -> 3 -> 33 -> NULL
所以你的问题是。。。我如何实现这一点?你必须更具体一点。你只想插入第一个位置?为什么不更新下一个到最后一个节点中的下一个指针,使其指向NULL,使最后一个节点成为新的头,更新其值并更新指向旧头的下一个指针。您提问的方式表明您需要一个函数,该函数只接受一个值作为输入,并将该值插入列表的头,从而删除最后一个节点。但是您的代码表明您希望能够将节点插入列表中的任何位置。你的问题应该更具体一些。@BenceKaulics是的,我想在列表的开头插入最后一个数字,这样你的问题是。。。我如何实现这一点?你必须更具体一点。你只想插入第一个位置?为什么不更新下一个到最后一个节点中的下一个指针,使其指向NULL,使最后一个节点成为新的头,更新其值并更新指向旧头的下一个指针。您提问的方式表明您需要一个函数,该函数只接受一个值作为输入,并将该值插入列表的头,从而删除最后一个节点。但是您的代码表明您希望能够插入
节点在列表中的任意位置。你的问题应该更具体一些。@BenceKaulics是的,我想在列表的开头插入最后一个数字,让最后一个数字消失谢谢你的帮助!非常感谢:因为您将新节点插入给shiftInsertAnywhere函数的节点位置之后,所以此函数无法将新节点插入列表的开头位置。@DavidBowling有一个单独的函数用于此目的:void shiftinsertrotint v。我提到shiftInsertAnywhere将在position之后插入。我的观点是,您有三个函数,其中一个或两个函数(如果您真的想保留deleteLast函数)就可以了。@DavidBowling两个函数有两个不同的用途。第三个函数中的共享部分,该函数在以后的任何地方都可能有用。我认为这样读代码更容易,仅此而已。谢谢你的帮助!非常感谢:因为您将新节点插入给shiftInsertAnywhere函数的节点位置之后,所以此函数无法将新节点插入列表的开头位置。@DavidBowling有一个单独的函数用于此目的:void shiftinsertrotint v。我提到shiftInsertAnywhere将在position之后插入。我的观点是,您有三个函数,其中一个或两个函数(如果您真的想保留deleteLast函数)就可以了。@DavidBowling两个函数有两个不同的用途。第三个函数中的共享部分,该函数在以后的任何地方都可能有用。我认为这样读代码更容易,仅此而已。