求解问题
请问一下大家一个课上的题目,想了好久,不晓得哪里错了,自己指针链表的基础太差了。。。 原题是这样的:将两个递增的有序链表合并为一个递增的有序链表,要求结果链表还使用原本两个链表的存储空间,不另外占用其他的存储空间。表中不允许有重复元素 我的想法是这样的:用双链表来操作,并且一直在list1中去操作,两个链表去比较,如果list2的元素比list1的元素大,就把list2的元素插入到list1比较的元素后,反之就插入到list1比较的元素前,但我的逻辑部分应该是没写错,但到要输出的时候就卡住了一小会,然后直接退出程序了,我又不是很会c语言编译器的debug,问题应该出在merge这个函数里。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
// 定义双链表节点结构
struct DNode {
int data;
struct DNode* prior;
struct DNode* next;
};
// 初始化 创建一个新的双链表节点
struct DNode* createDNode(int data) {
struct DNode* newNode = (struct DNode*)malloc(sizeof(struct DNode));//分配空间
newNode->data = data;
newNode->prior = NULL; //头节点
newNode->next = NULL; //首元节点
return newNode;
}
// 合并两个递增有序双链表
struct DNode* mergeSortedLists(struct DNode* list1, struct DNode* list2) {
struct DNode dummy;
dummy.prior = NULL;
dummy.next = NULL;
struct DNode* tail = &dummy;
while (list1 != NULL && list2 != NULL) {
if (list1->data < list2->data) {//list1的元素小于list2的元素情况
tail->next = list1; //新链表的首元指向小的
list1->prior = tail; //完善链表
list1 = list1->next; //当前元素比完,进一步
} else if (list1->data > list2->data) {
tail->next = list2; //同上
list2->prior = tail;
list2 = list2->next;
} else { // 处理重复元素,传进去一个就行
tail->next = list1;
list1->prior = tail;
list1 = list1->next;
list2 = list2->next;
}
tail = tail->next; //走完后新链表进一步
}
//扫尾 如果有某一个链表中元素没加进去 直接加进去
if (list1 != NULL) {
tail->next = list1;
list1->prior = tail;
}
if (list2 != NULL) {
tail->next = list2;
list2->prior = tail;
}
return dummy.next;
}
struct DNode* merge(struct DNode* list1, struct DNode* list2) {
struct DNode* temp1 = list1;
struct DNode* temp2 = list2;
while (temp1 != NULL) {
temp1->prior = NULL;
temp1 = temp1->next;
}
// 遍历list2,确保prior指针为空
while (temp2 != NULL) {
temp2->prior = NULL;
temp2 = temp2->next;
}
temp1 = list1;
temp2 = list2; // 将temp2的赋值提到循环之前
while (list1 != NULL && list2 != NULL) {
if (list1->data < list2->data) {
list2->prior = list1;
list2->next = list1->next;
list1->next->prior = list2;
list1->next = list2;
list1 = list1->next;
temp2 = temp2->next; // 更新temp2指针
} else if (list1->data > list2->data) {
list2->next = list1;
list2->prior = list1->prior;
list1->prior->next = list2;
list1->prior = list2;
list1 = list1->next;
temp2 = temp2->next; // 更新temp2指针
} else {
temp2 = temp2->next; // 处理重复元素,同时更新temp2指针
}
}
// 扫尾 如果有某一个链表中元素没加进去 直接加进去
if (list2 != NULL) {
while (temp1->next != NULL) {
temp1 = temp1->next;
}
temp1->next = list2;
list2->prior = temp1;
}
return list1;
}
// 打印双链表
void printList(struct DNode* list) {
struct DNode* current = list;//用临时指针代替以免指向混乱
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
struct DNode* insert(struct DNode* list) {
int n, data;
// scanf("%d", &n);//链表长度
cin >> n;
for (int i = 0; i < n; i++) {
cin >> data;//第一个元素
struct DNode* newNode = createDNode(data);
if (list == NULL) {
list = newNode;
} else {
struct DNode* temp = list;//临时指针
while (temp -> next != NULL) {
temp = temp -> next;//遍历直到指针末尾
}
temp -> next = newNode;//走完循环也就到了末尾
newNode -> prior = temp;//前驱指针赋值
}
}
return list;
}
int main() {
struct DNode* list1 = NULL;
struct DNode* list2 = NULL;
list1 = insert(list1);
list2 = insert(list2);
cout << "the first list: ";
printList(list1);
cout << "the second list: ";
printList(list2);
// struct DNode* mergedList = mergeSortedLists(list1, list2);
list1 = merge(list1, list2);
cout << "merge list: ";
printList(list1);
// 释放链表节点的内存
while (list1 != NULL) {
struct DNode* temp = list1;
list1 = list1->next;
free(temp);
}
while (list2 != NULL) {
struct DNode* temp = list2;
list2 = list2->next;
free(temp);
}
return 0;
}
这个思路感觉写复杂了,这道题的思路与合并两个有序数组的思路一样,只是连接各个结点的方式是使用指针
用一个指针指向小的节点然后用其中一个链表一个一个去指向它,然后不断向后走嘛?
对a,b链表的结点进行比较,使用一个指针cur连接上较小的结点,然后cur往后移,然后较小结点的指针往后移。
cur.next=a; // 假设a结点的值较小
cur=cur.next;
a=a.next;
然后继续循环比较、链接
谢谢,开始是这个思路,但是当时我以为这个算是另外开辟空间了,所以没考虑.
挺好,有限个变量算是O1的空间