C 旋转链接列表
我想旋转包含数字的链表。123应旋转为231。函数创建了23,但最后一个字符保持为空,为什么C 旋转链接列表,c,C,我想旋转包含数字的链表。123应旋转为231。函数创建了23,但最后一个字符保持为空,为什么 typedef struct node node; struct node{ char digit; node* p; }; void rotate(node** head){ node* walk= (*head); node* prev= (*head); char temp= walk->digit; while(walk->p
typedef struct node node;
struct node{
char digit;
node* p;
};
void rotate(node** head){
node* walk= (*head);
node* prev= (*head);
char temp= walk->digit;
while(walk->p!=NULL){
walk->digit=walk->p->digit;
walk= walk->p;
}
walk->digit=temp;
}
如何创建列表:
node* convert_to_list(int num){
node * curr, * head;
int i=0,length=0;
char *arr=NULL;
head = NULL;
length =(int) log10(((double) num))+1;
arr =(char*) malloc((length)*sizeof(char)); //allocate memory
sprintf (arr, "%d" ,num); //(num, buf, 10);
for(i=length;i>=0;i--) {
curr = (node *)malloc(sizeof(node));
(curr)->digit = arr[i];
(curr)->p = head;
head = curr;
}
curr = head;
return curr;
}
你的链表实际上有4个元素 您应该更改此行:
for(i = length; i >= 0 ; i--) {
致:
因为对于前一行,您将退出数组(在第一次迭代中访问arr[length]
)
通过此更改,您的
旋转功能可以正常工作。您的问题在于列表是向后存储的,并且您有一个指向“上一个”的指针,而不是指向“下一个”。这本应该是问题的一部分(我花了一段时间才明白这一点)
事实上,你用头的时候尾巴可能会更好。您应该考虑将指针存储到实际的头上,避免这种方式复制。在这种情况下,您只需要调整指针。如果轮换将是一项常见的任务,那么保留和更新一个额外的指针,可能位于列表中结构中,将付出努力(可以将任务从O(n)更改为O(1))
在任何情况下,旋转函数的问题在于,您在同一节点“头”上开始使用“行走”和“上一步”
void rotate(node** head){
node* walk= (*head);
node* prev=(*head)->p;
char temp= walk->digit;
while(prev!=NULL){
walk->digit=prev->digit;
walk= prev;
prev = prev->p;
}
walk->digit=temp;
}
你可以把大多数问题分解成简单的问题来解决
在这里,我将写下你的轮换如下:
void rotate(node **list) {
node *head = pop_head(list);
push_at_end(list, head);
}
node *pop_head(node **list) {
assert(*list);
node *head = *list;
*list = head->p;
head->p = 0;
return head;
}
void push_at_end(node **list, node *head) {
node *end = get_end(*list);
if (!end) {
*list = head;
} else {
end->p = head;
}
}
node *get_end(node *head) {
node *last = 0;
while (head) {
last = head;
head = head->p;
}
return last;
}
<>我用C++中的k节点编写了链表旋转代码。它对我非常有效。如果将k传递为1,它将把喜欢的列表旋转1个节点,在这里它解决了给定的问题。如果要将链表旋转k个节点,它仍然可以正常工作。请在下面找到
头文件:
public:
typedef struct node {
int data;
node *next;
} *Node;
Node head;
void rotateByk(int k);
以下代码用于.cpp文件
void DList::rotateByk(int k){
Node current = head;
Node kthNode;
int count = 1;
while(count<=k && current!=NULL){
kthNode = current;
current = current->next;
count++;
}
Node kthNextNode = current;
while(current->next!=NULL){
current = current->next;
}
current->next = head;
head = kthNextNode;
kthNode->next = NULL;
Node printNode = head;
while(printNode!=NULL){
cout << printNode->data << "\t";
printNode = printNode->next;
}
}
如果您有任何疑问,请告诉我。您的轮换代码似乎在移动数字,而不是重新链接列表,我认为这是练习的目的。对于等效的解决方案,您会得到一些分数,但这可能不是您应该演示的技术。您需要再分配一个字节—您的sprintf()
超出了分配的空间。你的长度是3,数字是123;您还需要分配一个空终止符。这一次你可以侥幸逃脱,因为malloc()
可能会分配至少8个字节的倍数,但这是一种不好的做法,如果你没有分配足够的空间,你迟早会被烧掉。但是我应该能够返回一个指向新节点的指针。旋转原型必须是这样的。什么是“向后”,或者你确定吗?数字(3)的最后一位存储在最后一个节点中,因为构造循环倒计时(索引2、1、0)而不是倒计时(索引0、1、2)格式化字符串-给出或接受原始错误。向后表示从“最后”到“第一”读取项目,特别是考虑到头指针指向“最后”元素,即本例中的3或2。
public:
typedef struct node {
int data;
node *next;
} *Node;
Node head;
void rotateByk(int k);
void DList::rotateByk(int k){
Node current = head;
Node kthNode;
int count = 1;
while(count<=k && current!=NULL){
kthNode = current;
current = current->next;
count++;
}
Node kthNextNode = current;
while(current->next!=NULL){
current = current->next;
}
current->next = head;
head = kthNextNode;
kthNode->next = NULL;
Node printNode = head;
while(printNode!=NULL){
cout << printNode->data << "\t";
printNode = printNode->next;
}
}
d1.rotateByk(1);