6.5 k个已排好序链表合并为一个排序链表

1 建立链表(带哨兵位的)
2 建立最小堆方法
3 合并已排好序的k个链表

  1 typedef int DataType;
  2 //建立链表
  3 class Link
  4 {
  5 private:
  6     struct Node
  7     {
  8         DataType data;
  9         Node *next;
 10     };
 11     Node *head; //哨兵位
 12 public:
 13     Link()
 14     {
 15         Init();
 16     }
 17     ~Link()
 18     {
 19         Delete();
 20     }
 21     void Init()
 22     {
 23         head = new Node;
 24         head->next = NULL;
 25     }
 26     void Delete()
 27     {
 28         for (Node *p = head; p != NULL;)
 29         {
 30             Node *pTemp = p->next;
 31             delete p;
 32             p = pTemp;
 33         }
 34         head = NULL;
 35     }
 36     bool Empty()
 37     {
 38         return head->next == NULL;
 39     }
 40     void Print()
 41     {
 42         for (Node *p = head->next; p != NULL; p = p->next)
 43         {
 44             cout << p->data << endl;
 45         }
 46     }
 47     //顺序插入 考虑两种情况 1.空表 2.当插入值是最大值的时候
 48     void SortInsert(DataType data)
 49     {
 50         Node *p = head;
 51         do 
 52         {
 53             if (p->next == NULL || p->next->data > data)
 54             {
 55                 Node *pNew = new Node;
 56                 pNew->data = data;
 57                 pNew->next = p->next;
 58                 p->next = pNew;
 59 
 60                 return;
 61             }
 62             p = p->next;
 63         } while (true);
 64     }
 65     //使用数组初始化列表
 66     void ArrayInsert(DataType array[], int size)
 67     {
 68         for (int i=0; i<size; ++i)
 69         {
 70             SortInsert(array[i]);
 71         }
 72     }
 73     //尾插法直接插入
 74     void Insert(DataType data)
 75     {
 76         Node *p = head;
 77         while(p->next != NULL)
 78         {
 79             p = p->next;
 80         }
 81 
 82         Node *pNew = new Node;
 83         pNew->data = data;
 84         pNew->next = NULL;
 85         p->next = pNew;
 86     }
 87     //去掉首结点并返回首结点的值
 88     int ExtractDate()
 89     {
 90         if (! Empty())
 91         {
 92             DataType data = head->next->data;
 93             Node *p = head->next;
 94             Node *pFirst = p->next;
 95 
 96             delete p;
 97             p = NULL;
 98 
 99             head->next = pFirst; 
100             return data;
101         }
102         return -1;
103     }
104     int GetData()
105     {
106         if (!Empty())
107         {
108             return head->next->data;
109         }
110     }
111     bool Find(const DataType data)
112     {
113         for (Node *p = head->next; p != NULL; p = p->next)
114         {
115             if (p->data == data)
116             {
117                 return true;
118             }
119         }
120         return false;
121     }
122     void Swap(Link &p)   //交换两个链表主要是交换 head
123     {
124         if (head != p.head)
125         {
126             Node *tmp = head->next;
127             head->next = p.head->next;
128             p.head->next = tmp;
129         }
130     }
131 };
132 //保持最小堆性质 参数inode为内部结点 注意结点从1开始,数组从0开始
133 void MinHeapify(int array[], int size, int inode)
134 {
135     int least= inode;                //父结点
136     int left = inode*2;                //左子结点
137     int right = inode*2+1;            //右子结点
138 
139     if (left <= size && array[left-1] < array[least-1])
140     {
141         least = left;
142     }
143     if (right <= size && array[right-1] < array[least-1])
144     {
145         least = right;
146     }
147 
148     if (least != inode)                    //父结点小于 左子结点 或者 右子结点
149     {
150         int temp = array[inode-1];            //子结点值与父结点值交换
151         array[inode-1] = array[least-1];
152         array[least-1] = temp;
153 
154         MinHeapify(array, size, least);      //再次验证被交换的值的子结点是否满足 最小堆性质
155     }
156 }
157 //建立最小堆 使每一个父结点小于子结点
158 void BuildMinHeap(int array[],int size)
159 {
160     for(int i=size/2; i>0; --i)     //最多有 size/2 个内部结点
161     {
162         MinHeapify(array, size, i);
163     }
164 }
165 //k个已排好序的链表合并为一个链表
166 //pLink 链表数组的地址, linkSize链表数组的大小, array 数组的地址, count数组的大小
167 void SortLink(Link *pLink, int linkSize, Link *link)
168 {
169     int *pArray = new int[linkSize]; //动态分配k个大小的数组
170     for (int i=0; i<linkSize; ++i)    //从k个链表中取首结点的值
171     {
172         pArray[i] = pLink[i].GetData();
173     }
174 
175     int j=0;
176     do 
177     {
178         BuildMinHeap(pArray,linkSize); //构造最小堆,即每个父结点小于或等于子结点,根结点为最小值
179         for (j=0; j<linkSize; ++j)
180         {
181             if(pLink[j].Find(pArray[0]))   //寻找最小值来自于哪一个链表
182             {
183                 link->Insert(pLink[j].ExtractDate());  //去掉并返回链表的的值(更新链表)
184                 break;
185             }
186         }
187         if (!pLink[j].Empty())  //确保取出值的链表不为空
188         {
189             pArray[0] = pLink[j].GetData();   //更新数组
190         }
191         else 
192         {
193             pArray[0] = pArray[linkSize-1];  
194             pLink[j].Swap(pLink[linkSize-1]);  //交换两个链表
195             --linkSize;
196         }
197     } while (linkSize != 0);
198 
199     delete [] pArray;
200 }
201 void main()
202 {
203     //检测是否有内存泄露 需要加头文件#include <crtdbg.h>
204     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
205 
206     Link k[5];
207 
208     int Array[5][5] = { {21, 12, 11, 10, 1}, 
209                         {22, 17, 16, 7, 2},
210                         {23, 18, 13, 8, 3},
211                         {24, 19, 14, 9, 4},
212                         {25, 20, 15, 6, 5}};
213 
214     for (int i=0; i<5; ++i)
215     {
216         k[i].ArrayInsert(Array[i],sizeof(Array[i])/sizeof(Array[i][0]));
217     }
218     //for (int i=0; i<5; ++i)
219     //{
220     //    k[i].Print();
221     //}
222 
223     Link link;
224 
225     SortLink(k, sizeof(k)/sizeof(k[0]), &link);
226 
227     link.Print();
228 
229     system("pause");
230 }

 (转载请注明作者和出处^_*  Seven++ http://www.cnblogs.com/sevenPP/  )

原文地址:https://www.cnblogs.com/sevenPP/p/3627368.html