某公司的一道面试题,跪了,希望能学到东西!解决的问题是将双向链表有序输出,直接上代码,不懂的可以在下面提问,有问题希望高手能提出来,或者能进行优化的,感觉在输出的代码上写的不好,希望大牛帮忙看下。
/*问题:将一个双向链表有序的输出,平均时间
复杂度为nlogn,不能退化为n方,辅助空间大小为
O(1)
从上面的问题看来,只能使用堆排序对双向链表进行排序
输出,才能满足所有要有,所以我们
将双向链表转化为完全二叉树
然后进行堆排序
1,2,3,4,5,6
将双向链表的向前向后指针转化为
左指针和右指针
思路:
1
/ \
2 3
/ \ /
4 5 6
*/
#include <iostream>
#include <vector>
using namespace std;
//双向链表的数据结构,这里使用就不使用模板了,直接使用int
typedef struct DoubleLinkList {
int value;
DoubleLinkList *pre; //指向前一个结点
DoubleLinkList *next; //指向后一个结点
} * pDoubleLinkList;
//功能:建立双向链表
//输入:整形容器array
//输出:双向链表的头指针
//注:单元测试函数,时间复杂度不计入总时间复杂度
pDoubleLinkList createDoubleLinkList(vector<int> &array){
if (array.empty())
return NULL;
pDoubleLinkList head = new DoubleLinkList;
head->value = array[0];
head->pre = head->next = NULL;
pDoubleLinkList preNode = head;
for( int i = 1; i != array.size(); i++){
pDoubleLinkList newNode = new DoubleLinkList;
newNode->value = array[i];
newNode->pre = preNode;
preNode->next = newNode;
newNode->next = NULL;
preNode = newNode;
}
return head;
}
//解决:将双向链表转化为二叉树
//输入:双向链表的头指针DoubleLinkList *head
//输出:二叉树的根结点指针,虽然这个结点依然是用双向链表的数据结构
//时间复杂度:n;
pDoubleLinkList DoubleLinkListToBinaryTree(pDoubleLinkList head){
if (head == NULL)
return NULL;
//指向当前结点的指针
pDoubleLinkList curNode = head;
//指向下一结点的指针
pDoubleLinkList nextNode = head->next;
//指向当前结点子结点的指针
pDoubleLinkList childNode = head->next;
while (curNode != NULL){
//对当结点的左右子结点进行赋值
if (childNode == NULL){
curNode->pre = NULL;
curNode->next = NULL;
}else{
curNode->pre = childNode;
childNode = childNode->next;
curNode->next = childNode;
if (childNode != NULL)
childNode = childNode->next;
}
curNode = nextNode;
if (nextNode != NULL)
nextNode = nextNode->next;
}
return head;
}
//功能:对二叉树进行堆排序(小顶堆)
//输入:无序二叉树的根结点
//输出:二叉堆的根结点
//时间复杂度:nlogn
void HeapSort(pDoubleLinkList root){
if (root == NULL)
return ;
HeapSort(root->pre);
HeapSort(root->next);
//如果这个结点有右子树
if (root->next != NULL){
//当前结点大于最小结点的值
if (root->pre->value < root->next->value){
if (root->value > root->pre->value){
swap(root->value, root->pre->value);
HeapSort(root->pre);
}
}else if (root->value > root->next->value){
swap(root->value, root->next->value);
HeapSort(root->next);
}
}else if (root->pre != NULL){ //如果当前结点没有右结点,但有左结点
//当前结点大于左结点的值
if (root->pre->value < root->value){
swap(root->value, root->pre->value);
HeapSort(root->pre);
}
}
}
//功能:返回二叉堆的最后一个结点
//输入:二叉堆的根结点,二叉堆的大小
//输出:二叉堆的最后一个结点指针
//时间复杂度:log(n)
pDoubleLinkList getEndNode(pDoubleLinkList *root, size_t length){
if (*root == NULL || length == 0)
return NULL;
if (length == 1){
pDoubleLinkList tmp = *root;
*root = NULL;
return tmp;
}
if (length == 2){
pDoubleLinkList tmp = (*root)->pre;
(*root)->pre = NULL;
return tmp;
}
if (length == 3){
pDoubleLinkList tmp = (*root)->next;
(*root)->next = NULL;
return tmp;
}
int i = 2;
while(i++)
if (pow(2, i) > length)
break;
int ipow = length - pow(2, i-1);
if (ipow >= pow(2, i-2))
return getEndNode(&(*root)->next, ipow);
else
return getEndNode(&(*root)->pre, ipow + 2);
}
//功能:将二叉堆有序输出
//输入:二叉堆的根结点pDoblueLinkList root
//输出:打印有序数组
void printfHeap(pDoubleLinkList root, size_t length){
int i = length;
while (root != NULL){
HeapSort(root);
cout<<root->value;
pDoubleLinkList endNode = getEndNode(&root, i);
i--;
if (root != NULL)
swap(root->value, endNode->value);
delete(endNode);
}
}
int main(int argc, char **argv){
vector<int> vec;
int tmp;
while(cin>>tmp){
vec.push_back(tmp);
}
pDoubleLinkList head = createDoubleLinkList(vec);
pDoubleLinkList root = DoubleLinkListToBinaryTree(head);
printfHeap(root, vec.size());
return 0;
}