将双向链表转化为二叉堆并有序输出

来源:互联网 发布:搜狐微博 知乎 编辑:程序博客网 时间:2024/06/11 23:44

某公司的一道面试题,跪了,希望能学到东西!解决的问题是将双向链表有序输出,直接上代码,不懂的可以在下面提问,有问题希望高手能提出来,或者能进行优化的,感觉在输出的代码上写的不好,希望大牛帮忙看下。



/*问题:将一个双向链表有序的输出,平均时间复杂度为nlogn,不能退化为n方,辅助空间大小为O(1)从上面的问题看来,只能使用堆排序对双向链表进行排序输出,才能满足所有要有,所以我们将双向链表转化为完全二叉树然后进行堆排序1,2,3,4,5,6将双向链表的向前向后指针转化为左指针和右指针思路:  1  /  \     2         3/ \        /    4   5      6   */#include <iostream>#include <vector>using namespace std;//双向链表的数据结构,这里使用就不使用模板了,直接使用inttypedef 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;}//功能:对二叉树进行堆排序(小顶堆)//输入:无序二叉树的根结点//输出:二叉堆的根结点//时间复杂度:nlognvoid 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);elsereturn 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;}

0 0