第二天-------單鏈表的基本操作(實驗報告),原始碼
1.掌握單鏈表的儲存特點及其實現。
2.掌握單鏈表的插入、刪除演算法及其應用演算法的程式實現。
二、實驗內容
1、實驗內容
編寫一個完整的程式,實現單鏈表的生成、插入、刪除、輸出等基本操作。
(1) 隨機產生或鍵盤輸入一組元素,建立一個帶頭結點的單向連結串列(無序)。
(2) 計算單鏈表的長度,遍歷單鏈表。
(3) 把單鏈表中的元素逆置(不允許申請新的結點空間)。
(4) 在單鏈表中刪除所有值為偶數的元素結點。
(5) 編寫在非遞減有序單鏈表中插入一個元素使連結串列元素仍有序的函式,並利用該函式建立一個非遞減有序單鏈表。
(6) *利用演算法5建立兩個非遞減有序單鏈表,然後合併成一個非遞增有序連結串列。
(7) *利用演算法5建立兩個非遞減有序單鏈表,然後合併成一個非遞減有序連結串列。
(8) *利用演算法1建立的連結串列,實現將其分解成兩個連結串列,其中一個全部為奇數,另一個全部為偶數(儘量利用已知的儲存空間)。
(9) *採用單鏈表實現一元多項式的儲存並實現兩個多項式相加並輸出結果。
(10) 在主函式中設計一個簡單的選單,分別除錯上述演算法。
(11) *綜合訓練:
1)利用連結串列實現一個班級學生資訊管理(資料錄入、插入、刪除、排序、查詢等,並能夠實現將資料儲存到檔案中)
2)約瑟夫環問題:設有n個人圍坐在圓桌周圍,從某個位置開始編號為1,2,3,…,n,坐在編號為1的位置上的人從1開始報數,數到m的人便出列;下一個(第m+1個)人又從1開始報數,數到m的人便是第二個出列的人;如此重複下去,直到最後一個人出列為止,得到一個出列的編號順序。例如,當n=8,m=4時,若從第一個位置數起,則出列的次序為4,8,5,2,1,3,7,6。試編寫程式確定出列的順序。要求用不帶頭結點的單向迴圈連結串列作為儲存結構模擬此過程,按照出列順序打印出個人編號。
2、主要資料型別與變數
1.型別定義
typedef int ElemType; //元素型別
typedef struct node
{
ElemType data;
struct node *next;
}LinkNode, *LinkList;
2.為了演算法實現簡單,建議採用帶頭結點的單鏈表。
3、演算法思想描述
宣告好資料結構的型別,開始編寫程式碼,先宣告一個結點,置為頭結點(本實驗中所有連結串列均有頭結點),插入資料時,宣告一個節點,資料域存放資料,原連結串列尾部結點指標域存放當前結點地址,弄好無序的連結串列,通過比較,使用頭插法,將無序連結串列置為有序連結串列,遍歷節點,當結點資料域為偶數時,將前面節點指標域存放需要刪除節點的指標域資料,然後完成刪除偶數結點。
三、系統測試。
2、測試結果
1. 建立單鏈表
2. 遍歷單鏈表
3. 計算單鏈表長度
4. 連結串列逆置
5. 刪 除 值為偶 數 節 點
6.生成有序單鏈表
7.合 並生成降 序 連結串列
8.合 並生成升 序 鏈 表
9.分解連結串列
附:程式原始碼
DS.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status;
LinkList.h
#include"DS.h"
typedefint Elemtype;
typedefstruct Node
{
Elemtype data;
struct Node *next;
}Lnode,*LinkList;
voidmenu(); /*選單*/
StatusInit_Linklist(LinkList &L); /*初始化空表*/
StatusCreat_Linklist(LinkList &L); /*尾插法建立單鏈表*/
voidDisp_Linklist(LinkList L); /*單鏈表遍歷*/
intlength_Linklist(LinkList L); /*計算單鏈表長度*/
voidReverse_Linklist(LinkList L); /*單鏈表逆置*/
voidDelEven_Linklist(LinkList L); /*刪除值為偶數的結點*/
StatusInsert_Linklist(LinkList L, int x); /*在有序單鏈表L中插入元素x,連結串列仍然有序*/
StatusCreatOrder_Linklist(LinkList &L); /*建立非遞減有序單鏈表*/
voidMergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc); /*兩個非遞減有序單鏈表La和Lb合併成一個非遞增有序連結串列Lc*/
voidMergeAscend_Linklist(LinkList La, LinkList Lb, LinkList &Lc); /*兩個非遞減有序單鏈表La和Lb合併成一個非遞減有序連結串列Lc*/
voidSplit_Linklist(LinkList La, LinkList &Lb); /*連結串列La按值分解成兩個連結串列,La全部為奇數,Lb全部為偶數*/
LinkList.cpp
#include "LinkList.h"
void menu()
{
printf("\t\t\t 單鏈表基本操作\n\n");
printf("\t\t\t1.建 立 單 鏈 表\n");
printf("\t\t\t2.遍 歷 單 鏈 表\n");
printf("\t\t\t3.計 算 鏈 表 長 度\n");
printf("\t\t\t4.鏈 表 逆 置\n");
printf("\t\t\t5.刪 除 值為偶 數 節 點\n");
printf("\t\t\t6.生成值有序單鏈表\n");
printf("\t\t\t7.合 並生成降 序 鏈 表\n");
printf("\t\t\t8.合 並生成升 序 鏈 表\n");
printf("\t\t\t9.分 解 鏈 表\n");
printf("\t\t\t0.退 出\n\n");
}
Status Init_Linklist(LinkList &L)
//初始化空表
{
L=(LinkList)malloc(sizeof(Lnode));
if(!L) return ERROR;
L->next=NULL;
return OK;
}
Status Creat_Linklist(LinkList &L)
//尾插法建立單鏈表
{
int x;
LinkList p,rear;
Init_Linklist(L);
rear = L;
printf("輸入-1表示輸入結束\n");
while(scanf("%d",&x),x != -1)
{
p =(LinkList)malloc(sizeof(Lnode));
if(!p) return ERROR;
p->data = x;
rear->next = p;
rear = p;
}
rear->next = NULL;
return OK;
}
void Disp_Linklist(LinkList L)
//單鏈表遍歷
{
LinkList p;
p = L->next;
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int length_Linklist(LinkList L)
//計算單鏈表長度
{
int count = 0;
LinkList p;
p = L->next;
while(p)
{
count++;
p = p->next;
}
return count;
}
void Reverse_Linklist(LinkList L)
//單鏈表逆置
{
LinkList p,q;
p = L->next;
L->next = NULL;
if(L != NULL){
while(p){
q = p;
p= p->next;
q->next =L->next;
L->next = q;
}
}else{
printf("連結串列為空");
}
}
void DelEven_Linklist(LinkList L)
//刪除值為偶數的結點
{
LinkList p,q;
p = L;
q = p->next;
while(q){
if(!(q->data&1)){
if(q->next == NULL){
p->next=NULL;
free(q);
}else{
q = q->next;
p->next =p->next->next;
}
}else{
q = q->next;
p = p->next;
}
}
}
Status Insert_Linklist(LinkList L, int x)
//在有序單鏈表中插入元素,連結串列仍然有序
{
LinkList p,q,r;//r為攜帶x的新結點
int flag=0;
r=(LinkList)malloc(sizeof(Lnode));
r->data = x;
if(L->next != NULL){
p=L;
q=p->next;
while(q){
if((r->data) <(q->data)){
flag=1;
r->next =p->next;
p->next = r;
break;
}else{
q=q->next;
p=p->next;
}
}
if(flag==0 &&p->next==NULL){
p->next=r;
r->next=NULL;
}
}else{
r->next=L->next;
L->next=r;
}
//free(r);
return OK;
}
Status CreatOrder_Linklist(LinkList &L)
//建立非遞減有序單鏈表
{
int x;
Init_Linklist(L);
printf("請輸入表中元素值,以-1結束\n");
while(scanf("%d",&x), x != -1)
Insert_Linklist(L, x);
return OK;
}
void MergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc)
//兩個非遞減有序單鏈表合併成一個非遞增有序連結串列
{
LinkList pa, pb, pc,p;
pa = La->next;
pb = Lb->next;
pc = Lc = La;
pc->next=NULL;
while(pa || pb){
if(!pa){
p=pb;
pb=pb->next;
}else if(!pb){
p=pa;
pa=pa->next;
}else if(pa->data <=pb->data){ //用頭插法
p=pa;
pa=pa->next;
}else{
p=pb;
pb=pb->next;
}
p->next=pc->next;
pc->next=p;
}
free(Lb);
}
void MergeAscend_Linklist(LinkList La, LinkList Lb, LinkList &Lc)
//兩個非遞減有序單鏈表合併成一個非遞減有序連結串列
{
LinkList pa, pb, pc;
pa = La->next;
pb = Lb->next;
pc = Lc = La;
while(pa && pb)
{
if(pa->data <=pb->data)
{
pc->next = pa; pc =pa; pa = pa->next;
}
else
{
pc->next = pb; pc =pb; pb = pb->next;
}
}
pc->next = pa ? pa : pb;
free(Lb);
}
void Split_Linklist(LinkList La, LinkList &Lb)
//連結串列按值分解成兩個連結串列,一個全部為奇數,另一個全部為偶數
{
LinkList p, q,r;
Lb=(LinkList)malloc(sizeof(Lnode));
Lb->next=NULL;
r=Lb;
p=La;
q=La->next;
while(q){
if(!(q->data&1)){
q=q->next;
r->next=p->next;
p->next=r->next->next;
r->next->next=NULL;
r=r->next;
}else{
q=q->next;
p=p->next;
}
}
}
Main.cpp
#include "LinkList.h"
int main()
{
int choice, length;
LinkList L, La, Lb, Lc;
while(1)
{
menu();
printf("選擇你的操作:");
scanf("%d",&choice);
switch(choice)
{
case 1:
if(Creat_Linklist(L))
printf("單鏈表建立成功\n");
else
printf("單鏈表建立失敗\n");
break;
case 2:
Disp_Linklist(L);
break;
case 3:
length =length_Linklist(L);
printf("單鏈表長度為:%d\n",length);
break;
case 4:
Reverse_Linklist(L);
printf("逆置後的連結串列為:\n");
Disp_Linklist(L);
break;
case 5:
DelEven_Linklist(L);
printf("新連結串列為:\n");
Disp_Linklist(L);
break;
case 6:
if(CreatOrder_Linklist(L))
{
printf("值有序連結串列為:\n");
Disp_Linklist(L);
}
else
printf("單鏈表建立失敗\n");
break;
case 7:
CreatOrder_Linklist(La);
CreatOrder_Linklist(Lb);
MergeDescend_Linklist(La, Lb, Lc);
printf("合併後的新連結串列為:\n");Disp_Linklist(Lc);
break;
case 8:
CreatOrder_Linklist(La);
CreatOrder_Linklist(Lb);
MergeAscend_Linklist(La, Lb, Lc);
printf("合併後的新連結串列為:\n");Disp_Linklist(Lc);
break;
case 9:
Creat_Linklist(L);
Split_Linklist(L,Lb);
printf("分裂後的新連結串列為:\n");
Disp_Linklist(L);
Disp_Linklist(Lb);
break;
case 0:
exit(-1);
default:
printf("輸入錯誤,請重新輸入\n");
menu();
}
}
return 0;
}