數據結構實驗二-單鏈表


#include <iostream>
#include "stdio.h"
#include "stdlib.h"
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2

typedef int Status;
//00定義線性表的鏈式存儲結構三個數據元素是原子類型不用struct,節點必須個域的結構體變量,數據結構用一個4B大小原子類型指針變量即可。

//定義數據對象、結點(含數據域、指針域)
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;//*ptrLNode; Linklist L L一看就是個鏈表;linklist r,p 一看r p給人的感覺也是鏈表,但實際不是; 不如ptrLNode r,p;  一看r和p就是指向節點的指針。
//定義數據結構(見上 *LinkList)。注:單鏈表每次插入必先循環找尾結點且不知長度,也可寫個結構體,為了和教材一致用上而不用下,僅供思考拓展
typedef Struct{
struct LNode *head;//指向頭結點
struct LNode *tail;//指向尾結點
int length;
}LinkList;//本實驗未采用該定義,僅供拓展思想用

//01初始化一個線性表
Status InitLinkList(LinkList &L);
//02創建一個包含n個正整數值的線性表(線性表的長度n和表中元素的值隨機輸入)
Status CreateLinkList_R(LinkList &L);
//03將一個數x插在第i個元素前
Status LinkListInsert(LinkList L, int i, ElemType x);
//04刪除第i個元素,並在刪除結束后輸出刪除元素的值
Status LinkListDelete(LinkList L, int i, ElemType &e);
//05查找指定元素e是否在線性表中存在,若存在返回此元素的位序,否則返回0
int LocateElem(LinkList L, ElemType e);
//06查找指定位置元素的值並輸出
Status Getelem(LinkList L, int i, ElemType &e);
//07輸出線性表中所有元素
Status TraverseLinkList(LinkList L);
//08銷毀單鏈表
Status DestroyLinkList(LinkList &L);
//09求單鏈表的長度
int ListLength(LinkList L);
//10將兩個有序表合並到一個新表LC中(重復的也合並進去,非遞減順序-->)
Status OrderLinkList_Merge(LinkList &LA, LinkList &LB, LinkList &LC);

int main()
{
ElemType e, x;
int i, k;
LinkList L = NULL;
do {
cout << "\n=========單鏈表的操作===========";
cout << "\n 1.初始化單鏈表";
cout << "\n 2.創建單鏈表";
cout << "\n 3.在第i個位置前插入元素x";
cout << "\n 4.刪除第i個元素";
cout << "\n 5.查找指定元素位置";
cout << "\n 6.查找指定位置元素";
cout << "\n 7.遍歷當前單鏈表";
cout << "\n 8.銷毀當前單鏈表";
cout << "\n 9.有序表合並";
cout << "\n 0.結束程序運行";
cout << "\n================================";
cout << "\n請輸入您的選擇(1,2,3,4,5,6,7,8,0):";
cin >> k;
switch (k)
{
case 1:
if (InitLinkList(L))
cout << " 初始化成功!";
else
cout << " 初始化失敗!";
break;
case 2:
if(CreateLinkList_R(L))
cout << " 創建成功!";
else
cout << " 創建失敗!";
break;
case 3:
cout << "請輸入插入元素的位置i及值x:";
cin >> i >> x;
LinkListInsert(L, i, x);
break;
case 4:
cout << "請輸入要刪除元素的位置i:";
cin >> i;
LinkListDelete(L, i, e);
cout << "刪除第" << i << "個元素的值為:" << e << endl;
break;
case 5:
cout << "請輸入要查找指定元素e:";
cin >> e;
cout << "該元素的位置是:" << LocateElem(L, e) << endl;
break;
case 6:
cout << "請輸入要查找元素的位置:";
cin >> i;
Getelem(L, i, e);
cout << "正在查找的第" << i << "個元素值是:" << e << endl;
break;
case 7:
cout << "當前單鏈表為:";
TraverseLinkList(L);
break;
case 8:
DestroyLinkList(L);
break;
case 9:
LinkList LA, LB, LC;
InitLinkList(LA);
InitLinkList(LB);
//InitLinkList(LC);//在合並代碼里有LC=LA,故不用初始化,因LC利用了LA的頭節點
cout << "請創建有序鏈表LA:";
CreateLinkList_R(LA);
cout << "請創建有序鏈表LB:";
CreateLinkList_R(LB);
cout << "LA、LB合並到LC:";
OrderLinkList_Merge(LA, LB, LC);
TraverseLinkList(LC);
break;
case 0:
break;
default:
cout << "無效選項,請重新輸入!" << endl;
}/*switch*/
} while (k != 0);
system("pause");
return 0;
}/*main*/

//01初始化一個線性表L
Status InitLinkList(LinkList &L)
{
L = new LNode; //創建一個頭結點
L->next = NULL;//指針域初始為空
return OK;
}
//02創建一個包含n個正整數值的線性表(線性表的長度n和表中元素的值隨機輸入---尾插法)
Status CreateLinkList_R(LinkList &L)
{
if (!L)InitLinkList(L); //線性表不存在則初始化一個線性表
//L = new LNode;
//L->next = NULL;
int n;
LinkList r, p;
r = L; //尾指針r指向尾結點(初始空表的尾結點為頭結點)
cout << "請輸入要創建單鏈表元素的個數n:";
cin >> n;
cout << "請輸入 " << n << " 個正整數:";
for (int i = 0; i<n; i++)
{
p = new LNode;
cin >> p->data;
p->next = NULL;
r->next = p;
r = p; //尾指針r指向新的尾結點
}
return OK;
}
//03將一個數x插在第i個元素前
Status LinkListInsert(LinkList L, int i, ElemType x)
{
if (!L)
{
cout << "鏈表不存在,請先初始化創建鏈表";
return ERROR; //表不存在
}
if ((i<1) || i>ListLength(L) + 1)
{
cout << "輸入的位置非法!";
return ERROR;
}//i值不合法
int j = 0;
LinkList p, s;
p = L;
while (j < i - 1)
{
p = p->next;
++j; //查找第i-1個結點,並另p指向該結點
}
s = new LNode;
s->data = x;
s->next = p->next; //將結點*s的指針域指向ai
p->next = s; //將結點*p的指針域指向s
return OK;
}
//04刪除第i個元素,並在刪除結束后輸出刪除元素的值
Status LinkListDelete(LinkList L, int i, ElemType &e)
{
if (!L)
{
cout << "鏈表不存在,請先初始化創建鏈表";
return ERROR; //表不存在
}
if ((i<1) || i>ListLength(L))
{
cout << "輸入的位置非法!";
return ERROR;
}//i值不合法
int j = 0;
LinkList p, q;
p = L;
while (j <i - 1)
{
p = p->next;
++j; //查找第i-1個結點,並讓p指向該結點。因是單鏈表,指針向右,后面的節點只能用前面的節點來表示
}
q = p->next; //q指向第i個要刪除的結點,起暫存的作用,以便del
p->next = q->next;
e = q->data;
delete q; //釋放q
return OK;
}
//05查找指定元素e是否在線性表中存在,若存在返回此元素的位序,否則返回0
int LocateElem(LinkList L, ElemType e)
{
if (!L)
{
cout << "鏈表不存在,請先初始化創建鏈表";
return ERROR; //鏈表不存在
}
LinkList p = L->next; //p指向第一個結點
int i = 1;
while (p&&p->data != e)
{
p = p->next;
i++;
}
if (i <= ListLength(L))
return i;
else
return 0;
}
//06查找指定位置元素的值並輸出
Status Getelem(LinkList L, int i, ElemType &e)
{
if (!L)
{
cout << "鏈表不存在,請先初始化創建鏈表";
return ERROR; //表不存在
}
if ((i<1) || i>ListLength(L))
{
cout << "輸入的位置非法!";
return ERROR;
} //i值不合法
LinkList p = L->next; //p指向第一個元素
int j = 1;
while (p&&j < i)
{
p = p->next;
++j;
} //找到第i個元素
e = p->data;
return OK;
}
//07輸出單鏈表中所有元素
Status TraverseLinkList(LinkList L)
{
if (!L)
{
cout << "鏈表不存在!";
return ERROR; //表不存在
}
LinkList p = L->next; //p指向第一個結點
while (p)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
return OK;
}
//08銷毀當前單鏈表
Status DestroyLinkList(LinkList &L)
{
if (!L)
{
cout << "鏈表不存在!\n";
return ERROR;
}
LinkList q;
while (L)
{
q = L; //q指向要刪除的結點
L = L->next; //L指向q的后繼結點
delete q;
} //銷毀以L為頭指針的單鏈表,釋放鏈表中所有節點的空間
L = NULL; //雖然頭節點占有的空間已經釋放,但指針變量L中的值沒有改變,為安全起見,置L為空,以防止對系統空間的訪問
cout << "鏈表已銷毀!" << '\n';
return OK;
}
//09求單鏈表的長度
int ListLength(LinkList L)
{
if (L == NULL)
{
cout << "鏈表不存在,請先選擇2創建單鏈表\n";
return 0;
}
LinkList p = L->next; //p指向鏈表第一個結點
int len = 0;
while (p)
{
len++;
p = p->next;
}
return len;
}
//10將兩個有序表LA\LB合並到一個新表LC中(重復的也合並進去,非遞減順序
Status OrderLinkList_Merge(LinkList &LA, LinkList &LB, LinkList &LC)
{
LinkList pa, pb, pc;
pa = LA->next;//pa意思是LA中還未插入LC剩余那一段單鏈表的指針,當然一開始從a1到an都未插入;
pb = LB->next;//同上
LC = LA; //LC在主函數中不需要初始化,聲明下即可。
pc = LC;//pc意思LC的尾結點指針,便於將上面的結點插入到LC,且插入后pc要指向新的尾結點
while (pa&&pb)
{
if (pa->data <= pb->data)
{
pc->next = pa;
pc = pa; //pc始終指向LC的尾節點
pa=pa->next; //pa指向下一節點
}
else
{
pc->next = pb;
pc = pb; //pc始終指向LC的尾節點
pb = pb->next;//pb指向下一節點
}
}//while循環中,pa pb不會同時為空,因為里面是if else 互斥,一次pc只能加一個節點
if (pa)
pc->next = pa;
else
pc->next = pb;//while循環結束后,pa、pb必有一空,一不空。
//pc->next = pa ? pa : pb;//一行即可替代上面if else,pc->next = pa含義是把pa賦值給pc->next,然后pc->next為空? 非空則pc->next=pa,則pc->next=pb
delete LB;
return OK;
}

//兩個鏈表按值大小進行合並參考:https://www.cnblogs.com/wwttsqt/p/7783179.html,其中合並沒調用子函數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM