这里我有一个包含函数的头文件:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node** top, node* newNode, node** last) {
node* current;
if (*top == NULL) {
*top = newNode;
} else if ((*top)->data >= newNode->data) {
newNode->next = *top;
newNode->next->prev = newNode;
*top = newNode;
if ((*top)->next == NULL) {
*last = *top;
}
} else {
current = *top;
while (current->next != NULL &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
if (current->next != NULL) {
newNode->next->prev = newNode;
}
current->next = newNode;
newNode->prev = current;
}
if ((*top)->next == NULL) {
*last = *top;
}
}
void insertionSort(node** top, node** last) {
node* sorted = NULL;
node* current = *top;
while (current != NULL) {
node* next = current->next;
current->prev = current->next = NULL;
sortedInsert(&sorted, current, last);
current = next;
}
*top = sorted;
}
node* deleteByPos(node* list, node** last, int position) {
int c = 0;
node* temp;
node* prev;
temp=list;
if (temp==NULL) {
printf("No nodes available to delete\n\n");
return list;
} else {
while(temp!=NULL && c != position) {
prev=temp;
temp=temp->next;
c++;
}
if (temp==NULL) {
printf("Reached end of list, position not available\n\n");
return list;
} else if (temp->next == NULL) {
prev->next=temp->next;
*last = prev;
free(temp);
return list;
} else {
prev->next=temp->next;
temp->next->prev = prev;
free(temp);
return list;
}
}
}
node* makeNode(int n) {
node* np = malloc(sizeof (node));
np->data = n;
np->prev = NULL;
np->next = NULL;
return np;
}
void printList(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->next;
}
}
void printListReverse(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->prev;
}
}
#endif /* driver_h */
和一个主文件:
#include "driver.h"
int main() {
int n;
node* np;
node* top;
node* last;
printf("Enter integers to add to list\n");
do {
if (scanf("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
if (top == NULL) {
top = np;
} else {
last->next = np;
np->prev = last;
}
last = np;
}
} while (n != 0);
printf("\n\n");
printf("You entered:\n");
printList(top);
printf("\n\n");
printf("In reverse:\n");
printListReverse(last);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
top = deleteByPos(top, &last, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(last);
insertionSort(&top, &last);
printf("From top after sort:\n");
printList(top);
printf("In reverse after Sort:\n");
printListReverse(last);
}
该程序所做的是获取用户的整数输入,将它们存储在双向链表中,删除用户定义点上的节点,然后执行插入排序。我要做的是使用以下代码保存指向sortedInsert函数中最后一个节点的指针:
if ((*top)->next == NULL) {
*last = *top;
}
但是,如果您输入6 5 3 1 9 8 4 2 7 4 2,则在位置2处删除,当反向打印时打印输出6 5 4 4 2 2 1.由于某种原因,它会跳过9 7 8我无法弄清楚为什么或如何解决这个问题。我该怎么做呢?
答案 0 :(得分:0)
使用列表,有助于绘制所有案例的图表。在列表上使用归纳来证明您的代码是正确的是很自然的。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> /* Asserting is useful when it come to lists especially. */
struct node {
struct node* next;
struct node* prev;
int data;
};
/* Saves you from dealing with 'top' and 'tail' every time. */
struct list {
struct node *head, *tail;
};
/* https://en.wikipedia.org/wiki/Insertion_sort */
void insertionSort(struct list* list) {
struct node* i = list->head, *j0, *j1;
while(i) {
j1 = i, j0 = j1->prev;
while(j0 && j0->data > j1->data) {
/* Swap. */
int temp = j0->data;
j0->data = j1->data;
j1->data = temp;
/* Decrement. */
j1 = j0;
j0 = j0->prev;
}
i = i->next;
}
}
/* Returns whether the position was deleted. */
int deleteByPos(struct list* list, int position) {
struct node* n;
assert(list);
/* Node n is the position's in the list. */
for(n = list->head; n && position; n = n->next, position--);
if (n==NULL) {
printf("No nodes available to delete\n\n");
return 0;
}
/* Fixme: If I'm not mistaken, there are 9 cases for you to be
mathematically certain this works, and I haven't tried them all.
Eg, 1 node, 2 nodes x2, 3 nodes x3, where the internal node is the 2nd of
the 3 nodes. */
if(n->prev == NULL) {
/* The first one. */
assert(list->head == n);
list->head = n->next;
if(n->next) n->next->prev = NULL;
} else {
/* Skip over. */
n->prev->next = n->next;
}
if(n->next == NULL) {
/* The last one. */
assert(list->tail == n);
list->tail = n->prev;
if(n->prev) n->prev->next = NULL;
} else {
/* Skip over. */
n->next->prev = n->prev;
}
n->prev = n->next = NULL; /* Helps in debugging. */
free(n);
return 1;
}
struct node* makeNode(struct list *list, int n) {
struct node* np = malloc(sizeof *np);
if(!np) return 0;
np->data = n;
np->prev = list->tail;
np->next = NULL;
/* Push it in the list. */
if(list->tail) {
assert(list->head != NULL && list->tail->next == NULL);
list->tail->next = np;
} else {
/* The first one. */
assert(list->head == NULL && list->tail == NULL);
list->head = np;
}
list->tail = np;
return np;
}
void printList(const struct list*const list) {
const struct node *n = list->head;
while (n) {
printf("%d\n", n->data);
n = n->next;
}
}
void printListReverse(const struct list*const list) {
const struct node *n = list->tail;
while (n) {
printf("%d\n", n->data);
n = n->prev;
}
}
int main(void) {
int n;
struct list list = { 0, 0 };
printf("Enter integers to add to list\n");
while(scanf("%d", &n) == 1 && n)
if(!makeNode(&list, n)) return perror("node"), EXIT_FAILURE;
printf("\n\n");
printf("You entered:\n");
printList(&list);
printf("\n\n");
printf("In reverse:\n");
printListReverse(&list);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
printf("You entered %d.\n", n);
deleteByPos(&list, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(&list);
insertionSort(&list);
printf("From top after sort:\n");
printList(&list);
printf("In reverse after Sort:\n");
printListReverse(&list);
return EXIT_SUCCESS;
}
*理想情况下,退出时可以释放内存。
答案 1 :(得分:0)
使用sentinel节点而不是NULL来指示列表的结尾通常要简单得多。因此,空列表由头尾指向自身的节点组成。添加元素后,sentinel-&gt; next是列表中的第一个,sentinel-&gt; prev是列表中的最后一个。这将删除您必须在代码中测试NULL的许多情况:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node* top, node* newNode) {
node* current = top;
while (current->next != top &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
newNode->next->prev = newNode;
current->next = newNode;
current->next->prev = current;
}
void insertionSort(node* top) {
node* current = top->next;
// make top an empty ring so can append to it
top->next = top->prev = top;
while (current != top) {
node* next = current->next;
sortedInsert(top, current);
current = next;
}
}
node* deleteByPos(node* top,int position) {
int c = 0;
node* temp = top->next;
while (true) {
if (temp == top) {
printf("Reached end of list, position not available\n\n");
return top;
}
if (c == position) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
return top;
}
temp = temp->next;
c++;
}
}
node* makeNode(int n) {
node* np = malloc(sizeof(node));
np->data = n;
np->prev = np;
np->next = np;
return np;
}
void printList(node* top) {
for (node* np = top->next; np != top; np = np->next) {
printf("%d\n", np->data);
}
}
void printListReverse(node* top) {
for (node* np = top->prev; np != top; np = np->prev) {
printf("%d\n", np->data);
}
}
#endif /* driver_h */
主文件:
#include "driver.h"
int main() {
int n;
node* np;
node* top;
top= makeNode(0);
printf("Enter integers to add to list\n");
do {
if (scanf_s("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
np->prev = top->prev;
top->prev = np;
top->prev->next = top;
np->prev->next = np;
}
} while (n != 0);