單連結串列增刪改查和歸併插入排序

wzm10455發表於2012-12-09
/*
 * fun.c
 *
 *  Created on: 2012-12-6
 *      Author: wzm
 */

//初始化連結串列
#include "head.h"
void Init(pList mylist)
{
//	puts("-----------------------------------------------------選擇您需要的操作--------------------------------------------------------------------------");
//	puts("-----------------------------------------------------1.增加出現的年齡群-----------------------------------------------------------------------");
//	puts("-----------------------------------------------------2.根據年齡n來查詢該記錄所存在的位置-----------------------------------------");
//	puts("-----------------------------------------------------3.根據第n個人來查詢這個人的年齡------------------------------------------------");
//	puts("-----------------------------------------------------4.在位置n處插入你需要插入的人的歲數-----------------------------------------");
//	puts("-----------------------------------------------------5.刪除位置為n的人的記錄---------------------------------------------------------------");
//	puts("-----------------------------------------------------6.刪除年齡為n的人的記錄---------------------------------------------------------------");
//	puts("-----------------------------------------------------7.修改輸入年齡對應的人的歲數------------------------------------------------------");
//	puts("-----------------------------------------------------8.修改輸入對應的人的歲數-------------------------------------------------------------");
//	puts("-----------------------------------------------------9.依次輸出記錄-------------------------------------------------------------------------------");
//	puts("-----------------------------------------------------10.銷燬記錄------------------------------------------------------------------------------------");
	mylist->head=NULL;
	mylist->size=0;
}
//建立連結串列
int  Create(pList mylist)
{
	pelem tmp=mylist->head;//先儲存一下頭結點
	int i;
	while(scanf("%d",&i))
	{
	pelem p=(pelem *)malloc(sizeof(struct M_List_));//構造空間
	if(mylist->head==NULL)
	{
		mylist->head=p;
		p->age=i;
		mylist->size++;
		p->next=NULL;
		tmp=mylist->head;
	}
	else
	{
	tmp->next=p;//在棧空間裡面每一次呼叫原來建立的內容會被銷燬,為了防止這個只能用堆空間裡面的malloc來開闢空間,這個是會一直儲存的,
	p->age=i;//將要放的那個元素 讓所在原來位置的值的下一個節點所指向,
	mylist->size++;
	p->next=NULL;//指向尾節點
	tmp=tmp->next;//讓所在原來位置的值的下一個節點所指變成現在所在的節點,這就有利於下一次建立連結串列
	}
	}
	printf("%d 個數\n",mylist->size);
   return mylist->size;//返回成功錄入的元素的個數
}

//依次顯示節點
 int display(pList mylist)
{
	 if(mylist->head==NULL)
	 {
		 return -1;
	 }
	 else
	 {
	pelem tmp=mylist->head;
	while(tmp!=NULL)
	{
		puts("");
		printf("age為%d\n",tmp->age);
		tmp=tmp->next;
	}
	return mylist->size;
	 }
}


//查詢值為n的節點
 pelem Find1(pList mylist,int n)
{
		pelem tmp=mylist->head;
		int n1=0;
		 while(tmp->age!=n)
		 {
			 n1++;
			 tmp=tmp->next;
		 }
		 printf("該年齡人物所處的位置為:%d",n1);
		 if(tmp->age==n)
		 {
			 return tmp;
		 }
		 else
		 {
			 return NULL;
		 }
}
//查詢第N個位置的值
 pelem Find2(pList mylist,int n)
 {
	 pelem tmp=mylist->head;
	 if(n==0)
	 {
		 return tmp;
	 }
	 else
	 {
		 int i=1;
		 while(i<=n-1)
		 {
			 tmp=tmp->next;
			 i++;
		 }
		 return tmp;
	 }
 }
int Insert(pList mylist,unsigned int num)
{
	pelem tmp=mylist->head;
	if(num==0)
	{
		int i;
		getchar();
		scanf("%d",&i);
		pelem p=(pelem *)malloc(sizeof(struct M_List_ ));
		p->next=tmp;
		p->age=i;
		mylist->size++;
	}
	else	if(num>0)
	{
		int i,j=0;
		pelem p=(pelem *)malloc(sizeof(struct M_List_ ));
		p->age=10;
		while(j!=num-2)
		{
			    j++;
				tmp=tmp->next;
		}
		p->next=tmp->next;
		tmp->next=p;
		mylist->size++;
	}
	return mylist->size;
}

//連結串列的修改
int Change(pList mylist,int n)
{
	pelem tmp=Find1(mylist,n);
	puts("請輸入您想要修改的年齡!");
	getchar();//要注意清除上一個回車符
	 scanf("%d", &tmp->age);
	 puts("恭喜您,修改成功,請檢視!");
	 printf("年齡修改為%d",tmp->age);
	 return 0;
}
int Change1(pList mylist,int n)//根據第n個值來修改資料
{
	    pelem tmp=Find2(mylist,n);
		puts("請輸入您想要修改的年齡!");
		getchar();//要注意清除上一個回車符
		 scanf("%d", &tmp->age);
		 puts("恭喜您,修改成功,請檢視!");
		 printf("年齡修改為%d",tmp->age);
		 return 0;
}
//刪除第n個位置的節點
int Delete1(pList mylist,int n)
{
	pelem tmp1=mylist->head;
	if(n==0)
	{
		mylist->head=tmp1->next;
		free(tmp1);
		return 0;
	}
	else
	{
		int i=1;
		while(i<n)
		{
			i++;
			tmp1=tmp1->next;
		}
		if(i!=mylist->size-1)
		{
			tmp1=tmp1->next->next;
			free(tmp1->next);
		}
		else
		{
			tmp1=NULL;
			free(tmp1->next);
		}
	}
	return 0;
}

//刪除某個值的節點
int Delete2(pList mylist,int n)
{
	pelem tmp1=mylist->head;//每次操作都要儲存起始位置
	//因為這是一個不帶頭結點的連結串列,因此要分三種情況
	if(tmp1->age==n)//當是第一個時
	{
		mylist->head=tmp1->next;
		free(tmp1);
		return 0;
	}
	pelem tmp2=mylist->head->next;
	if(tmp2->age==n)
	{
		tmp1->next=tmp2->next;
		free(tmp2);
	}
	else
	{
		while(tmp2->age!=n &&tmp2!=NULL)
		{
			tmp2=tmp2->next;
			tmp1=tmp1->next;
		}
			if(tmp2!=NULL)
			{
				tmp1->next=tmp2->next;
				free(tmp2);

			}
			else
			{
				return -1;
			}
	}
	return 0;
}
void Destory_List(pList mylist)
{
	pelem tmp=mylist->head;
	if(tmp!=NULL)
	{
	tmp=tmp->next;
	free(mylist->head);
	mylist->head=tmp->next;
	}
	printf("刪除成功!");
}

void InsertionSort(pList mylist)
{
	//把整個資料分成兩部分,一部分有序,一部分無序,然後從無序中拿出一個插入有序中
	//1.先打斷連結串列,把剩餘的無序的刪除掉
	//2.後插入有序的,找位置,然後插入
	//3.這是一個迴圈,直到排序結束
	pelem p=mylist->head->next;//連結串列分割
	mylist->head->next=NULL;

	//刪除
	pelem tmp=p->next;//tmp指向下一個,儲存剩下的連結串列
	p->next=NULL;

	//插入
	pelem p2=mylist->head;//
       while(p)
       {
        if((p2->age)>=(p->age))
        {
            p->next=p2;
            mylist->head=p;
        }
        else if((p2->age)<=(p->age)&&p2->next==NULL)//當那個位置是在末尾時,p要指向空
        {
                    p->next=p2->next;
                    p->next=NULL;
        }
        else if((p2->age)<=(p->age)&&(p2->next->age>=p->age))//當在兩個數之間時
        {
                p->next=p2->next;
                p2->next=p;
        }
        else if((p2->age)<=(p->age)&&(p2->next->age<=p->age))//當大於兩個數時
        {
                p2=p2->next;
                continue;//這個continue的作用
        }
		p=tmp;
		if(tmp!=NULL)
		{
		tmp=tmp->next;
		}
		p2=mylist->head;//要換成新的頭,
	}
}

void ListCat(pList mylist1,pList mylist2)//兩個連結串列的拼接
{
	pelem ptr1=mylist1->head;
	pelem ptr2=mylist2->head;
	int size1=mylist1->size;
//	int size2=mylist2->size;
	if(mylist1->head)
	{
		while(size1-1)
		{
			ptr1=ptr1->next;
			size1--;
		}
		ptr1->next=ptr2;
	}
}

void MergeList(pList mylist1,pList mylist2,pList mylist3)//歸併排序兩個連結串列,第三個連結串列用來記錄
{
		pelem ptr1=mylist1->head;
		pelem ptr2=mylist2->head;
		pelem p=(pelem *)malloc(sizeof(pelem));
		pelem ptr3=p;
		mylist3->size=0;
		while(ptr1&&ptr2)
		{
			if(ptr1->age<ptr2->age)
			{
				ptr3->next=ptr1;
				ptr1=ptr1->next;
				ptr3=ptr3->next;
			}
			else
			{
				ptr3->next=ptr2;
				ptr2=ptr2->next;
				ptr3=ptr3->next;
			}
			mylist3->size++;
		}
		while(ptr1!=NULL)
		{
			ptr3->next=ptr1;
			ptr1=ptr1->next;
			ptr3=ptr3->next;
			mylist3->size++;
		}
		while(ptr2!=NULL)
		{
			ptr3->next=ptr2;
			ptr2=ptr2->next;
			ptr3=ptr3->next;
			mylist3->size++;
		}
		mylist1->head=p->next;
}
void FuncFor_All(pList mylist)
{

	puts("選擇您的操作");
	int n;
	scanf("%d",&n);
	getchar();
	switch(n)
	{
	case 1:
	{
			puts("----------------------------建立過程進行中--------------------------------");
			printf("總人數%d\n",Create(&mylist));
			break;
	}
	case 2:
	{
			puts("請您輸入你需要查詢的那個人的年齡");
			int i;
			getchar();
			scanf("%d",&i);
			pelem a=Find1(&mylist,i);
			break;
	}
	case 3:
	{
			puts("請您輸入你需要查詢的那個人的位置");
			int i;
			getchar();
			scanf("%d",&i);
			pelem a=Find2(&mylist,i);
			printf("你需要查詢的那個人的年齡為:%d",a->age);
			break;
	}
	case 4:
	{
				puts("請您輸入你需要插入的那個人的位置");
				int i;
				getchar();
				scanf("%d",&i);
				printf("插入後人數總和為:%d",Insert(& mylist,i));
				break;
	}
	case 5:
	{

					puts("請您輸入你需要刪除的那個人的位置");
					int i;
					getchar();
					scanf("%d",&i);
					printf("刪除後人數總和為:%d",Delete1(& mylist,i));
					break;

	}
	case 6:
	{
					puts("請您輸入你需要刪除的年齡的那個人");
					int i;
					getchar();
					scanf("%d",&i);
					Delete2(& mylist,i);
					break;
	}
	case 7:
	{
				puts("請您輸入你需要更改的那個人的位置");
				int i;
				getchar();
				scanf("%d",&i);
				printf("更改後人的年齡為:%d",Change(& mylist,i));
				break;
	}
	case 8:
	{
				puts("請您輸入你需要更改的年齡");
				int i;
				getchar();
				scanf("%d",&i);
				printf("更改後人的年齡為:%d",Change1(& mylist,i));
				break;
	}
	case 9:
	{
			display(&mylist);
		break;
	}
	case 10:
	{
		puts("-------------------------------------------刪除連結串列中,請稍後----------------------------------------");
		puts("..................................................................");
		Destory_List(&mylist);
		break;
	}
	default:puts("!!!!!!!!!!您輸入有誤!!!!!!!!!!!!!!!!!!!!!!!");
	break;
	}
}



/*
 * head.h
 *
 *  Created on: 2012-12-6
 *      Author: wzm
 */
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
typedef struct M_List_
{
	int age;
	struct M_List_ *next;//p指向下一個節點
}elem,*pelem;

typedef struct Y_List_//整個連結串列的屬性,資料就是一個包,強調分裝性
{
	struct M_List_ *head;//頭指標
	unsigned size;//大小是連結串列的長度
}List,*pList;//這時真實的列表

//連結串列需要初始化,即要產生一個序列,要知道第一個連結串列的節點的位置
void FuncFor_All(pList mylist);//老師說懂c的人會加下劃線,嘿嘿,那偶就加一下把!
void Init(pList mylist);//初始化
int Create(pList mylist);//建立
int display(pList mylist);//連結串列所有節點展示
pelem  Find1(pList mylist,int n);//這和是根據值為n來查詢那個節點,返回值為那個節點的指標
pelem  Find2(pList mylist,int n);//這和是根據個數為第n個元素來查詢那個節點,返回值為那個節點的指標
int Insert(pList mylist,unsigned int num);//插入某個節點
int Delete1(pList mylist,int n);//根據個數為第n個來刪除該元素
int Delete2(pList mylist,int n);//根據所輸入的值來進行刪除
int Change(pList mylist,int n);//根據輸入的值來修改資料
int Change1(pList mylist,int n);//根據第n個值來修改資料
void Destory_List(pList mylist);//銷燬整個連結串列
void InsertionSort(pList mylist);//插入排序
void ListCat(pList mylist1,pList mylist2);//連結串列的拼接
void MergeList(pList mylist1,pList mylist2,pList mylist3);//歸併排序兩個連結串列
void MergeList1(pList mylist1,pList mylist2,pList mylist3);


相關文章