1. 程式人生 > >鏈式單鏈表

鏈式單鏈表

題目:

    構造一個單鏈表,實現建立、刪除、插入、查詢等功能。

解析:

初始化單鏈表,即單鏈表的表頭指標為空

void initlist(node **pnode)
{
	*pnode = NULL;
	printf("初始化成功!\n");
}

 列印連結串列元素,遍歷連結串列 

//列印連結串列元素,遍歷連結串列 
void printinfo(linklist list)
{
	lnode *head;
	if(head == NULL)//連結串列為空 
		cout<<"連結串列為空!"<<endl;
	//連結串列不為空則輸出打印出元素 
	else 
	{
		cout<<"連結串列元素為:";
		for(head=list;head!=NULL;head=head->next)//第一個指向list
			cout<<head->data<<" ";
		cout<<endl<<endl;
	}
}

知曉連結串列長度建立一個線性連結串列

從線性表的第一個元素開始依次獲取表中的資料元素,每取得一個數據元素,就為該資料元素生成一個新的鏈結點,將取得的資料元素的資料資訊送新的結點的資料域的同時,將新結點的指標域置為NULL,然後將新的鏈結點插入到連結串列的尾部。當取第1個數據元素時,連結串列為空,此時只需要將新的鏈結點的地址傳送即可 。

linklist creat(int n)
{
	linklist p,r,next = NULL;
	elemtype a;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);//獲取一個數據元素 
		p = (linklist)malloc(sizeof(node));//申請一個新的結點 
		p->data = a;
		p->next = NULL;//連結串列末尾指標域置空 
		if(next == NULL)
			next = p;
		else
			r->next = p;//將新的結點連結在連結串列的尾部 
		r=p;//指標變數總是指向連結串列的末尾 
	} 
	return next;
}

求連結串列的長度(1)

首先將指標指向連結串列的第一個鏈結點,然後遍歷連結串列,指標變數每指向一個鏈結點,計數器就加1,遍歷結束後,計數器的資料就是連結串列的長度。

int length1(linklist list)
{
	linklist p = list;
	int n = 0;
	while(p!=NULL)
	{	
		n++;//計數器累加 
		p = p->next; //指標p指向下一個鏈結點 
	}
	return n;//返回連結串列的長度 
} 

求連結串列的長度(2)

遞迴結構,即每個鏈結點的指標域均指向一個線性連結串列,它所指向的鏈結點為該連結串列的第1個鏈結點。

int length2(linklist list)
{
	if(list!=NULL)
		return 1+length2(list->next);
	else
		return 0; 
} 

測試連結串列是否為空

如果指標指向的第1個鏈結點為NULL,則連結串列為空,否則連結串列非空。

void isempty(linklist list)
{
	if(list == NULL)
        printf("連結串列為空\n");
    else
    	printf("連結串列非空\n");
} 

確定元素item線上性連結串列中的位置

從連結串列的第1個鏈結點開始,依次遍歷連結串列,查詢其是否與給定值item相匹配。如果相匹配則輸出item的位置,否則則輸出連結串列中該值不存在。

linklist find(linklist list,elemtype item)
{
	linklist p = list;
	int place = 1;//計數器記錄位置
	while(p !=NULL && p->data != item)//查詢是否匹配
	{
		place++;
		p = p->next;
	}
	if(p !=NULL && p->data == item)
		cout<<"item的位置為:"<<place<<endl;
	else
		cout<<"item不存在!"<<endl;
}

在非空線性連結串列的第1個鏈結點前插入一個數據信息為item的鏈結點

首先申請一個新的鏈結點,將其資料資訊item置於新鏈結點的資料域內,然後將第1個結點的指標list送入新結點的指標域內,同時將新結點的地址賦予給list,從而新結點插入連結串列的最前面,由此完成插入。

void insert1(linklist &list,elemtype item)
{
	//list中存放連結串列的首地址
	linklist p;
	p = (linklist)malloc(sizeof(node));//申請一個新的連結點
	p ->data = item;//將item送新結點的資料域
	p ->next = list;//將list送新結點的指標域
	list = p;//list指向新結點 
} 

非空線性連結串列的末尾插入一個數據信息為item的連結點

首先設定一個指標變數,使其指向連結串列的第1個鏈結點,然後反覆執行直到其等於NULL,此時指標指向連結串列的末尾鏈結點,然後將item送入申請的新結點的資料域的同時,將新的結點的指標域置為NULL,最後將新的結點的地址送入指標變數指向的鏈結點的指標域中,由此完成插入。

void insert2(linklist list,elemtype item)
{
	//list存放連結串列的首地址
	linklist p,r;
	r = list;
	while(r->next!=NULL)
		r = r->next;//找到連結串列末尾結點的地址 
	p = (linklist)malloc(sizeof(node));//申請一個新的連結點
	p ->data = item;//將item送新結點的資料域
	p ->next = NULL;//新結點的指標域置為NULL 
	r ->next =p;//插入連結串列的末尾 
}

線上性連結串列中的第i個鏈結點後面插入一個數據信息為item的連結點

從第1個結點開始查詢直到第i個結點,然後將新的結點插到它們的後面。如果不存在第i個鏈結點則輸出不存在。如果存在第i個鏈結點則申請一個新的結點,然後將item送入新的結點的資料域,並且將新的結點插到第i個鏈結點之後,如此插入成功。

void insert4(linklist list,int i,elemtype item)
{
	linklist p,q = list;
	int j=1;
	while(j<i&&q!=NULL)
	{
		q = q ->next;
		j++; 
	}//尋找第i個鏈結點
	if(j!=i||q==NULL)
		printf("連結串列中不存在第i個鏈結點");
	p = (linklist)malloc(sizeof(node));//申請一個新的鏈結點
	p ->data = item;//將item送新結點的資料域
	p ->next = q ->next;
	q ->next = p;//將新結點插入第i個鏈結點之後
}

在按值有序連結的線性連結串列中插入一個數據信息為item的鏈結點

先為被插入的鏈結點申請一個新的鏈結點,然後從連結串列的第一個鏈結點開始順序查詢插入位置,在查詢的過程中保留當前鏈結點的直接前驅結點的位置,由此進行插入。

void insert5(linklist &list,elemtype item)
{
	linklist p,q,r;
	p = (linklist)malloc(sizeof(node));
	p ->data = item;
	if(list==NULL||item<list->data)//若連結串列為空或者item小於第1個鏈結點 
	{
		p ->next = list;//將新的鏈結點插在連結串列最前面 
		list = p;//list指向被插入的新結點 
	}	
	else
	{
		q = list;
		while(q!=NULL&&item>=q->data)//尋找插入位置 
		{
			r = q;
			q = q->next;
		}
		p->next = q;
		r->next = p;//將新的鏈結點插在q指示的鏈結點後面 
	} 
}

銷燬一個線性連結串列

設定一個指標變數,先將其指向連結串列的第1個鏈結點,然後遍歷整個連結串列,過程中刪除並釋放鏈結點。

void deletelist(linklist &list)
{
	linklist p = list;
	while(p!=NULL)
	{
		list = p->next;//儲存下一個鏈結點的位置
		free(p);//刪除並釋放當前的鏈結點
		p = list;//下一個鏈結點成為當前鏈結點
	}
} 

刪除第k個結點

從連結串列第一個鏈結點開始,找到第k個鏈結點,然後刪除該結點並釋放空間。

lnode* getelem(linklist list,int k)
{
    lnode* s=list;
    while(k)
    {
        s=s->next;
        k--;
    }
    return s;
}

void deletelist3(linklist list,int k)
{
    lnode* p=list;
    lnode* q=NULL;
    p=getelem(list,k-1);
    q=p->next;
    p->next=q->next;
    free(q);

}

逆轉一個線性連結串列

通過改變鏈結點指標域中的地址來依次改變資料元素的關係。

//逆轉一個線性連結串列
void invert(linklist &list)
{
	linklist p,q,r;
	p = list;
	q = NULL;
	while(p!=NULL)
	{
		r = q;
		q = p;
		p = p->next;
		q->next = r;
	}
	list = q;
} 

複製一個線性連結串列

如果一個連結串列為空,則輸出連結串列為空。如果連結串列非空則複製連結串列所指的鏈結點,並將該鏈結點的指標賦給另外一個鏈結點,然後複製鏈結點後面一個鏈結點,最後返回另一個連結串列的第1個鏈結點

//複製一個線性連結串列
linklist copy(linklist lista)
{
	linklist listb;
	if(lista==NULL)
		cout<<"連結串列為空"<<endl;
	else
	{
		listb = (linklist)malloc(sizeof(node));
		listb->data = lista->data;
		listb->next = copy(lista->next); 
	}
	return listb;
} 

附:原始碼

#include<iostream>
#include<cstdio>
#include<malloc.h>
using namespace std;
typedef int elemtype;

typedef struct node
{
	elemtype data;//資料域 
	struct node *next;//指標域 
}lnode,*linklist;//定義一個線性連結串列的型別 

void initlist(linklist *pnode)
{
	*pnode = (linklist)malloc(sizeof(lnode));
	if(*pnode == NULL)
		printf("初始化失敗\n\n");
	else
	{
		(*pnode)->next =NULL;
		printf("初始化成功!\n\n"); 
	}
}

linklist creat(int n)
{
	linklist p,r,next = NULL;
	elemtype a;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);//獲取一個數據元素 
		p = (linklist)malloc(sizeof(node));//申請一個新的結點 
		p->data = a;
		p->next = NULL;//連結串列末尾指標域置空 
		if(next == NULL)
			next = p;
		else
			r->next = p;//將新的結點連結在連結串列的尾部 
		r=p;//指標變數總是指向連結串列的末尾 
	} 
	return next;
}

//求線性連結串列的長度
int length1(linklist list)
{
	linklist p = list;
	int n = 0;
	while(p!=NULL)
	{	
		n++;//計數器累加 
		p = p->next; //指標p指向下一個鏈結點 
	}
	return n;//返回連結串列的長度 
} 

//求線性連結串列的長度(遞迴)
int length2(linklist list)
{
	if(list!=NULL)
		return 1+length2(list->next);
	else
		return 0; 
} 

//測試線性連結串列是否為空
void isempty(linklist list)
{
	if(list == NULL)
        printf("連結串列為空\n");
    else
    	printf("連結串列非空\n");
} 

//確定元素item線上性連結串列中的位置
linklist find(linklist list,elemtype item)
{
	linklist p = list;
	int place = 1;
	while(p !=NULL && p->data != item)
	{
		place++;
		p = p->next;
	}
	if(p !=NULL && p->data == item)
		cout<<"item的位置為:"<<place<<endl;
	else
		cout<<"item不存在!"<<endl;
}

//在非空線性連結串列的第1個鏈結點前插入一個數據信息為item的鏈結點
void insert1(linklist &list,elemtype item)
{
	//list中存放連結串列的首地址
	linklist p;
	p = (linklist)malloc(sizeof(node));//申請一個新的連結點
	p ->data = item;//將item送新結點的資料域
	p ->next = list;//將list送新結點的指標域
	list = p;//list指向新結點 
} 

//非空線性連結串列的末尾插入一個數據信息為item的連結點
void insert2(linklist list,elemtype item)
{
	//list存放連結串列的首地址
	linklist p,r;
	r = list;
	while(r->next!=NULL)
		r = r->next;//找到連結串列末尾結點的地址 
	p = (linklist)malloc(sizeof(node));//申請一個新的連結點
	p ->data = item;//將item送新結點的資料域
	p ->next = NULL;//新結點的指標域置為NULL 
	r ->next =p;//插入連結串列的末尾 
}


//線上性連結串列中的第i個鏈結點後面插入一個數據信息為item的連結點
void insert4(linklist list,int i,elemtype item)
{
	linklist p,q = list;
	int j=1;
	while(j<i&&q!=NULL)
	{
		q = q ->next;
		j++; 
	}//尋找第i個鏈結點
	if(j!=i||q==NULL)
		printf("連結串列中不存在第i個鏈結點");
	p = (linklist)malloc(sizeof(node));//申請一個新的鏈結點
	p ->data = item;//將item送新結點的資料域
	p ->next = q ->next;
	q ->next = p;//將新結點插入第i個鏈結點之後
}

//在按值有序連結的線性連結串列中插入一個數據信息為item的鏈結點
linklist insert5(linklist &list,elemtype item)
{
	linklist p,q,r;
	p = (linklist)malloc(sizeof(node));
	p ->data = item;
	if(list==NULL||item<list->data)//若連結串列為空或者item小於第1個鏈結點 
	{
		p ->next = list;//將新的鏈結點插在連結串列最前面 
		list = p;//list指向被插入的新結點 
	}	
	else
	{
		q = list;
		while(q!=NULL&&item>=q->data)//尋找插入位置 
		{
			r = q;
			q = q->next;
		}
		p->next = q;
		r->next = p;//將新的鏈結點插在q指示的鏈結點後面 
	} 
	return list;
}

//銷燬一個線性連結串列
void deletelist(linklist &list)
{
	linklist p = list;
	while(p!=NULL)
	{
		list = p->next;//儲存下一個鏈結點的位置
		free(p);//刪除並釋放當前的鏈結點
		p = list;//下一個鏈結點成為當前鏈結點
	}
} 


lnode* getelem(linklist list,int k)
{
    lnode* s=list;
    while(k)
    {
        s=s->next;
        k--;
    }
    return s;
}

void deletelist3(linklist list,int k)
{
    lnode* p=list;
    lnode* q=NULL;
    p=getelem(list,k-1);
    q=p->next;
    p->next=q->next;
    free(q);

}

//逆轉一個線性連結串列
void invert(linklist &list)
{
	linklist p,q,r;
	p = list;
	q = NULL;
	while(p!=NULL)
	{
		r = q;
		q = p;
		p = p->next;
		q->next = r;
	}
	list = q;
} 

//複製一個線性連結串列
linklist copy(linklist lista)
{
	linklist listb;
	if(lista==NULL)
		cout<<"連結串列為空"<<endl;
	else
	{
		listb = (linklist)malloc(sizeof(node));
		listb->data = lista->data;
		listb->next = copy(lista->next); 
	}
	return listb;
} 


//列印連結串列元素,遍歷連結串列 
void printinfo(linklist list)
{
	lnode *head;
	if(head == NULL)//連結串列為空   
		cout<<"連結串列為空!"<<endl;
	//連結串列不為空則輸出打印出元素 
	else 
	{
		cout<<"連結串列元素為:";
		for(head=list;head!=NULL;head=head->next)//第一個元素指向list  
			cout<<head->data<<" ";
		cout<<endl<<endl;
	}
}

int main()
{

	lnode *list = NULL; 
	elemtype length = 0,item;
	
	//測試連結串列是否為空
	cout<<"測試連結串列是否為空!"<<endl;
	isempty(list);
	
	//初始化單鏈表,即單鏈表的表頭指標為空
	cout<<endl<<"初始化連結串列!"<<endl;
	initlist(&list);//連結串列初始化 
	
	//知曉連結串列長度建立一個線性連結串列
	cout<<"建立連結串列!"<<endl; 
	int m;//長度 
	cout<<"輸入連結串列長度:";
	scanf("%d",&m);
	cout<<"輸入資料:";
	list = creat(m);//資料元素需要接收回來賦給list 
	printinfo(list); 
	
	//求線性連結串列的長度
	cout<<"連結串列的長度:";
	cout<<length1(list)<<endl;
	
	//遞迴求連結串列的長度
	cout<<"遞迴求連結串列的長度:";
	cout<<length2(list)<<endl<<endl; 
	
	//測試連結串列是否為空
	cout<<"測試連結串列是否為空!"<<endl;
	isempty(list);
	
	//確定元素item線上性連結串列中的位置
	cout<<endl<<"確定item在連結串列中的位置!"<<endl; 
	cout<<"輸入item:";
	scanf("%d",&item); 
	find(list,item);
	
	//在非空線性連結串列的第1個鏈結點前插入一個數據信息為item的鏈結點
	cout<<endl<<"在連結串列第1個鏈結點插入item!"<<endl; 
	cout<<"輸入item:";
	scanf("%d",&item);
	insert1(list,item);
	printinfo(list); 
	
	//非空線性連結串列的末尾插入一個數據信息為item的連結點
	cout<<endl<<"在連結串列末尾插入item!"<<endl; 
	cout<<"輸入item:";
	scanf("%d",&item);
	insert2(list,item);
	printinfo(list); 
	
	//線上性連結串列中的第i個鏈結點後面插入一個數據信息為item的連結點
	cout<<endl<<"在連結串列中的第i個鏈結點後面插入item!"<<endl; 
	cout<<"輸入item:";
	scanf("%d",&item);
	elemtype i;
	cout<<"輸入i:";
	scanf("%d",&i);
	insert4(list,i,item);
	printinfo(list);

	//在按值有序連結的線性連結串列中插入一個數據信息為item的鏈結點
	cout<<endl<<"在按值有序連結的線性連結串列中插入item!"<<endl; 
	cout<<"輸入item:";
	scanf("%d",&item);
	list = insert5(list,item);
	printinfo(list);
	
	
	//刪除第 k 個節點
	cout<<endl<<"刪除第k個結點!"<<endl;
	elemtype k;
	cout<<"輸入k:";
	cin>>k;
	deletelist3(list,k);
	printinfo(list);
	
	//逆轉一個線性連結串列
	cout<<endl<<"逆轉連結串列!"<<endl; 
	invert(list);
	printinfo(list);
	
	//複製一個線性連結串列
	cout<<"複製連結串列!"<<endl; 
	copy(list);
	printinfo(list);

    //銷燬一個線性連結串列
	cout<<endl<<"銷燬連結串列!"<<endl;
	deletelist(list);
	isempty(list);
	
	return 0;
}