关于链表的各种细节问题

链表由于和指针密切相关,不免会出现各种关于指针方面的问题,处理不当就会导致bug众多,可能是找不到该指针,可能是数据被覆盖……因此在写程序的开头,就需要先定好实现的大体方法,通过图的方式先把算法描述一遍再开始写程序。


一、关于c和c++的使用问题:

如果准备用C写,就尽量避免使用C++封装的部分,如果准备用C++写,就尽量少用malloc、free等表达形式

如链表中,申请新的内存空间时用list l1=(list)malloc(sizeof(struct element))的形式,如果list中有string类型的变量 在cin时候会报错,因为C无法明确知道string的大小,因此开辟内存空间的时候会出现Bug。


二、关于排序的问题:

对于链表的排序涉及到了两个结构的交换。

1.若采用交换指针的方式,则该名称指代的地址不变,位置发生改变。即:

这种情况下tail位于head前面,因此无法进行排序算法的实现。

2.可以采取交换数据的方式,但是如果进行大数据量的结构交换,则该方法过于繁杂。

3.查找该节点的前一个节点可以写一个previous函数,通过函数调用查找该节点,还可以使用双向链表进行查找。

4.链表中实现选择排序的一个较好办法是构造一个新链表,将已排序内容放入新的链表,最后再将新链表的表头放入原始链表,通过这种方法实现排序。


下面为使用链表的图书管理系统的源代码:

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

typedef struct element* list;
typedef struct element* position;

struct element{
	string ID;
	string NAME;
	float price;
	struct element* Next;
};

void input(list List){                                //输入数据
	while(1){
		position temp;
		temp=new element();
		cin>>temp->ID; 
		if(temp->ID=="finish")break;                  //当遇到finish结束
		cin>>temp->NAME; 
		cin>>temp->price;
		position p=List;
		while(p->Next!=NULL){
			p=p->Next;
		}
		temp->Next=NULL;
		p->Next=temp;
	}
}

void output(list l){                                 //输出数据
	position p;
	p=l->Next;
	if(p==NULL)cout<<"无法查到数据!"<<endl;
	while(p!=NULL){
		cout<<p->ID<<" "<<p->NAME<<" "<<p->price<<endl;
		p=p->Next;
	}
}

position previous(list l1,position p){                //查找前一个位置
	position temp=new element();
	temp=l1;
	while(temp->Next!=p){
		temp=temp->Next;
	}
	return temp;
}
void find_name(string NAME,list l){                 //根据名称查找
	position p;
	p=l->Next;
	while(p!=NULL){
		if(p->NAME==NAME){
			cout<<p->ID<<" "<<p->NAME<<" "<<p->price<<endl;
		}
		p=p->Next;
	}
}
position find_id(string ID,list l){                     //根据ID查找
	position p;
	p=l->Next;
	while(p->ID!=ID&&p!=NULL){
		p=p->Next;
	}
	if(p==NULL)printf("查找错误!\n");
	else cout<<p->ID<<" "<<p->NAME<<" "<<p->price<<endl;
	return p;
}



position mid(list l1,position head,position tail){       //快排的具体实现步骤
	position Flag=l1->Next;
	float flag=head->price;
	position p=new element();
	p->ID=head->ID;
	p->NAME=head->NAME;
	p->price=head->price;
	while(head!=tail){
		position temp=new element();  
		while(head!=tail&&tail->price<=flag){
			tail=previous(l1,tail);
		}
		head->NAME=tail->NAME;
		head->ID=tail->ID;
		head->price=tail->price;
		while(head!=tail&&head->price>=flag){
			head=head->Next;
		}
		tail->ID=head->ID;
		tail->NAME=head->NAME;
		tail->price=head->price;
	}

	head->ID=p->ID;
	head->NAME=p->NAME;
	head->price=p->price;	
	while(Flag->ID!=p->ID){
			Flag=Flag->Next;
	}
	return Flag;
}
void quick_sort(list l1,position head,position tail){      //快排的递归过程
	if(head!=tail){
		position middle=mid(l1,head,tail);
		quick_sort(l1,head,previous(l1,middle));   
		quick_sort(l1,middle->Next,tail);
	}
}

list select_sort(list l1){								//选择排序
	list l2=(list)malloc(sizeof(struct element));       //排序链表的头指针
	position Tail;  //排序链表的尾指针
	position p;//用于比较的指针
	position pre;//最大节点的前一节点
	position max;//指向最大的节点
	l2->Next=NULL;
	while(l1->Next!=NULL){
		for(p=l1->Next,max=l1->Next;p!=NULL;p=p->Next){           //挑选最大节点
			if(p->price>max->price){
				max=p;
				pre=previous(l1,p);
			}
		}
		if(l2->Next==NULL){                                      //将最大节点放入新链表末尾
			l2->Next=max;
			Tail=max;
		}
		else {
			Tail->Next=max;
			Tail=max;
		}
		if(max==l1->Next){										 //在原链表中去掉该节点
			l1->Next=l1->Next->Next;
		}
		else {
			pre->Next=max->Next;
		}
		if(l2->Next!=NULL){                                       
			Tail->Next=NULL;									//新链表末尾置空
		}
	}
	l1=l2;
	return l1;
}
int main(){
	list l1; 
	l1 = new element();   //此处不能用(list)malloc(sizeof(struct element));否则使用string时会报错
	l1->Next=NULL;
	while(1){
		printf("--------------菜单-----------------\n");
		printf("--------1.输入图书信息-------------\n");
		printf("--------2.输出图书信息-------------\n");
		printf("--------3.查找图书信息-------------\n");
		printf("--------4.对图书信息进行排序-------\n");
		printf("--------5.退出系统-----------------\n");
		int c;
		cin>>c;
		switch(c){
			case 1:
				{
					cout<<"请输入数据,并以finish表示结束。输入格式为:ISBN 名称 价格  "<<endl;
					input(l1);
				}break;
			case 2:
				output(l1);
				break;
			case 3:
				{
					cout<<"按ID查找请按1,按书名查找请按2:"<<endl;
					int x;
					cin>>x;
					if(x==1)
					{	
						printf("请输入该书的ID号:");
						string id;
						cin>>id;
						find_id(id,l1);
					}
					else if(x==2){
						printf("请输入该书的书名:");
						string name;
						cin>>name;
						find_name(name,l1);
					}
					else {
						cout<<"输入错误!"<<endl;
					}
				}
				break;
			case 4:                                 
				{
					cout<<"采用快速排序请按1,采用选择排序请按2"<<endl;
					int y;
					cin>>y;
					if(y==1){
						position head=l1->Next;
						position tail=l1->Next;
						while(tail->Next!=NULL)
						tail=tail->Next;
						quick_sort(l1,head,tail);
					}
					else if(y==2){
						l1=select_sort(l1);
					}
					else {
						cout<<"输入错误!"<<endl;
					}
				 }
				break;
			case 5:
				exit(0);
				break;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值