本題在之前發佈過,但發現方法略有複雜。本次將更新一下最簡單的思想方法 。點擊查看原題出處
思想:
- 改進:不需要對每個結點的左鏈域進行置空初始化,因爲最後還是會重新賦值。只需要對頭結點 L 初始化: L->prior = L;
- 原方法:每次選出最小元素,採用尾插法排序,較爲繁瑣,而且指針變量太多。新方法:每次選出最大元素,進行頭插法。這樣代碼更爲簡潔,同樣可以實現從小到大排列
附上全部代碼(運行結果)
//.h文件
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include <iostream>
#include <fstream>
using namespace std;
#define OK 1
#define ERROR 0
typedef int Status;
typedef int ELEMTYPE;
typedef struct LNode
{
ELEMTYPE data; //數據域
bool flag; //標誌位 判斷是否選中爲最大元素
struct LNode *prior; //前驅
struct LNode *next; //後繼
}LNode,*LinkList;
Status initLinkList(LinkList &L) //初始化鏈表
{
L = (LNode *)malloc(sizeof(LNode));
if (!L)
{
cout << "空間不足\n";
return ERROR;
}
L->prior = L->next = L;
}
Status CreateLinkList(LinkList &L) //尾插法建表 讀文件
{
fstream file;
file.open("data.txt",ios::in);
if (!file)
{
cout<<"打開文件失敗\n";
return ERROR;
}
LNode *rear = L;
while (!file.eof())
{
LNode *p = (LNode *)malloc(sizeof(LNode));
file >> p->data;
p->flag = false;
p->next = L;
L->prior = p;
p->prior = rear;
rear->next = p;
rear = p;
}
return OK;
}
int getLength(LinkList L) //獲取鏈表長度
{
LNode *p = L->next;
int n = 0;
while(p != L)
{
p = p->next;
n++;
}
return n;
}
void Upgrade_1(LinkList &L) //左鏈域從小到大
{
L->prior = L; //讓左鏈域初始化
LNode *p,*q;
for (int i = 1; i <= getLength(L); i++) //右鏈域循環 每次找出一個最大元素
{
p = L->next;
ELEMTYPE max = -99999; //足夠小
while (p != L)
{
if (p->data > max && p->flag == false)
{
max = p->data;
q = p;
}
p = p->next;
}
q->flag = true; //若最大元素被選中 則標記true 不再參與下輪比較
q->prior = L->prior; //頭插法 倒序排列 實現從小到大排列
L->prior = q;
}
}
void Upgrade_2(LinkList &L) //左鏈域從大到小
{
L->prior = L; //讓左鏈域初始化
LNode *p,*q;
for (int i = 1; i <= getLength(L); i++) //右鏈域循環 每次找出一個最小元素
{
p = L->next;
ELEMTYPE min = 99999; //足夠小
while (p != L)
{
if (p->data < min && p->flag == false)
{
min = p->data;
q = p;
}
p = p->next;
}
q->flag = true; //若最大元素被選中 則標記true 不再參與下輪比較
q->prior = L->prior; //頭插法 倒序排列 實現從大到小排列
L->prior = q;
}
}
void visitRlink(LinkList L) //右鏈域遍歷
{
LNode *p = L->next;
while (p != L)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
void visitLlink(LinkList L) //左鏈域遍歷
{
LNode *p = L->prior;
while (p != L)
{
cout << p->data << " ";
p = p->prior;
}
cout << endl;
}
#endif
//.cpp文件
#include "stdafx.h"
#include "LinkList.h"
int _tmain(int argc, _TCHAR* argv[])
{
LinkList L; //雙循環鏈表
initLinkList(L); //初始化鏈表
CreateLinkList(L); //建表
Upgrade_1(L);
cout << "右鏈域(正常順序):";
visitRlink(L);
cout << "左鏈域(從小到大):";
visitLlink(L);
initLinkList(L);
CreateLinkList(L);
Upgrade_2(L);
cout << "左鏈域(從大到小):";
visitLlink(L);
return 0;
}