数据结构——线性表

顺序表代码

单链表代码

循序表算法

#include<stdio.h>
#include<string.h>
#include"malloc.h" 
# define MaxSize 100
typedef int ElemType;
typedef int Status;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define LIST_INIT_SIZE 100   // 线性表存储空间的初始分配量
#define LIST_INCREMENT 10    // 线性表存储空间的分配增量

typedef struct {
  ElemType *elem;            // 存储空间基址
  int length;                // 当前长度
  int listsize;              // 当前分配的存储容量
} SqList;

int list_initialize(SqList &L)
{
	L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
	if(L.elem ==NULL) return 0;
	L.length=0;
	L.listsize=LIST_INIT_SIZE;
	return 1;
}
int list_length(SqList &L)
{
	return L.length;
	
}
int list_insert(SqList &L,int i,ElemType e)
{
	ElemType *p;
	if(i<1||i>=L.length+1)
	return ERROR;
	if(L.length >= L.listsize) {    // 当前存储空间已满,增加容量
        ElemType *newbase = (ElemType *)realloc(L.elem,
                (L.listsize + LIST_INCREMENT) * sizeof(ElemType));
        if(!newbase)
            return ERROR;
			                 // 存储分配失败
        L.elem = newbase;                  // 新基址
        L.listsize += LIST_INCREMENT;      // 增加存储容量
    }
    ElemType *q = &(L.elem[i - 1]);       // q为插入位置
    for(p = &(L.elem[L.length - 1]); p >= q; --p)
        {*(p + 1) = *p;	}	         // 插入位置及之后的元素右移
    *q = e;       			// 插入e
    L.length++;   			// 表长增1
    return OK;
}
int list_delete(SqList &L,int i,ElemType &e)
{
	if(i<1||i>L.length)
	return 0;
	
	ElemType *p;
	ElemType *q=&L.elem[i-1];
	e=*q;
	p=&L.elem[L.length -1];
	for(q;q<p;q++)
	{
		*q=*(q+1);
	 } 
	 L.length--;
	 return 0;
}
Status DestroyList(SqList &L)
{ // 初始条件:顺序线性表L已存在。操作结果:销毁顺序线性表L
    free(L.elem);
    L.elem = NULL;
    L.length = 0;
    L.listsize = 0;
    return OK;
}
void dispList(SqList L)//遍历顺序表 
{
    for(int i = 1; i <= L.length; i++)
        printf("%d ", L.elem[i - 1]);
        printf("\n"); 
}
void swap(ElemType &x, ElemType &y)	//交换x和y
{  ElemType tmp=x;
   x=y;  y=tmp;
}
void SwapMaxMin(SqList &L)	//交换L中最大值元素与最小值元素
{  int i,maxi,mini;
   maxi=mini=0;
   for (i=1;i<L.length;i++)
     if (L.elem[i]>L.elem[maxi])
         maxi=i;
     else if (L.elem[i]<L.elem[mini])
         mini=i;
   swap(L.elem[maxi],L.elem[mini]);
}
int Deletek(SqList &L,int i,int k)//删除顺序表从I开始的K个元素 
{  
   int j;
   if (i<1 || k<1 || i+k-1>L.length)
      return 0;			//判断i和k是否合法
   for (j=i+k-1;j<L.length;j++)   	//将元素前移k个位置
      L.elem[j-k]=L.elem[j];
   L.length-=k;			//L的长度减k
   return 1;
}
void Move(SqList &L)//将所有奇数移到所有的偶数前边
{  
   int i=0,j=L.length-1;
   while (i<j)
   {  while (L.elem[i]%2==1) i++;	//从前向后找偶数
      while (L.elem[j]%2==0) j--;	//从后向前找奇数
      if (i<j)
         swap(L.elem[i],L.elem[j]);	//交换这两元素
   }
}
void DeleteMinus(SqList &L)//删除其中所有值为负整数的元素
{  
   int i, k=0;
   for (i=0;i<L.length;i++)
     if (L.elem[i]>=0)	//将不为负数的元素插入到L中
     {  L.elem[k]=L.elem[i];
        k++;
     }
   L.length=k;			//重置L的长度
}
void reverse(int R[],int m,int n)	  //将R[m..n]逆置
{ int i;
   int tmp;
	for (i=0;i<(n-m+1)/2;i++)
	{	tmp=R[m+i];		  //将R[m+i]与R[n-i]进行交换
	R[m+i]=R[n-i];
	R[n-i]=tmp;
	}
}
int ListReverse(int R[],int n,int p)	    //循环左移
{	if (p<=0 || p>=n)
	return 0;
	else
	{	reverse(R,0,p-1);
	reverse(R,p,n-1);
	reverse(R,0,n-1);
	return 1;
	}
}
Status deleteSame (SqList &L)//删除顺序表中值重复的元素
{
    if (L.length == 0) {
        printf ("表空,不能删除!\n");
        return ERROR;
    };
    int i, j, k = 0;
    for (i = 1; i < L.length; i++) {
        for (j = 0; j <= k; j++)
            if (L.elem[i] == L.elem[j])
                break;
        if (j > k && ++k != i)
            L.elem[k] = L.elem[i];
    }
    L.length = k + 1;
    return OK;
}
 int main ()
{
	int n=1,a;
	int temp;
	
	SqList P;
	list_initialize(P);
	int location,number;
	//将这个顺序表前十个空间,赋值为0-9,
	
    for(int i=0;i<10;i++){
        P.elem[i]=i-5;
        printf("%d ",P.elem[i]);
        P.length++;
    }
    printf("\n");
	printf("顺序表---菜单---\n");
	 
	printf("插入元素请输入:1;\n删除元素请输入:2\n遍历链表请输入:3\n求链表长度输入:4\n销毁链表请输入:5\n");
	printf("交换顺序表中最大值元素与最小值元素:6\n删除顺序表从I开始的K个元素 :7\n将所有奇数移到所有的偶数前边:8\n");
	printf("删除其中所有值为负整数的元素:9\n循环左移p(0<p<n)个位置:10\n删除顺序表中值重复的元素:11\n");
	while(n)
	{
		printf("请输入要进行的操作数:\n");
		scanf("%d",&a); 
		switch(a)
		{
			case 1: 
					printf("输入要插入顺序表的 位置,元素:\n"); 
					scanf("%d %d",&location,&number); 
					list_insert(P,location,number);
					break;
			case 2:  printf("输入要删除顺序表元素的 位置,保存返回元素用number:\n"); 
					scanf("%d",&location); 
					list_delete(P,location,number);
				    break;
			case 3: dispList(P); 
				 	break;
			case 4: printf("目前顺序表长度:");
					
					printf(" %d \n",list_length(P));
					break;
			case 5: DestroyList(P);
			 		break;
			case 6: SwapMaxMin(P);	
					break;
			case 7: printf("输入要删除顺序表第i个元素开始的k个元素-- i k:\n"); 
				scanf("%d %d",&location,&number); 
					Deletek(P,location,number);
					break; 
			case 8: Move(P);	
					break;	
			case 9: DeleteMinus(P);	
					break;	
			case 10:printf("需要循环左移p位p:");
					scanf("%d",&number);
					ListReverse(P.elem,P.length,number);	
					break;
			case 11:deleteSame (P);	
					break;					
		}
			
	}
	
 }

单链表算法

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#include<malloc.h>
typedef int ElemType;
typedef int Status;
#define OK 1
#define ERROR 0
// -----结点的c语言描述------
//L List是头结点   
typedef struct node{
	ElemType data;
	struct node *next;
}LNode,*LinkList; 
////////////////////////////////////////////
Status InitList_L(LinkList &L)
{
	//操作结果:构造一个空的线性表l
	//产生头结点,并使L指向此头结点
	L=(LinkList)malloc(sizeof(LNode));
	if(!L)//存储分配失败
	      return ERROR;
	L->next=NULL;//指针域为空
	return OK; 
}
//////////////////////////////////////
Status DestroyList(LinkList &L)
{
	//
	LinkList p;
	while(L){
		p->next;
		free(L);
		L=p;
	}
	return OK;
}
////////////////////////////////////////////////////
int ListLength(LinkList L)
{
//初始化条件:线性表L已经存在。操作结果:返回L中数据元素个数 
	int i=0;
	LinkList p=L->next;//p指向第一个结点 
	while(p){//没到表尾 
		i++;
		p=p->next;
	}
	return i;
}
//////////////////////////////////////////
int LocateElem(LinkList L, ElemType e)
{
//操作结果:返回L中的第一个与e相等的数据元素的位序
//若这样的数据元素不存在,则返回值为0
   int i=0;
   LinkList p=L->next;
   while(p)
   {
   	i++;
   	if(p->data==e)//找到这样的数据元素 
   	return i;
   	p=p->next;
   	
   }
   return 0;
 } 
 /////////////////////////////////////////
 Status ListInsert_L(LinkList &L,int i,ElemType e)
 {
 	//在带头结点L的单链表的第i个元素之前插入元素e
	 LinkList p,s;
	 p=L;
	 int j=0;
	 while(p&&j<i-1)
	 {//寻找第i-1个结点 
	 	p=p->next;
	 	++j;
	 	
	 }
	 if(!p||j>i-1)
	 { printf("插入的位置不存在\n"); 
	 return ERROR;//i小于1或者大于表长
	 }
	 
	 s=(LinkList)malloc(sizeof(LNode));//生成新结点 
	 s->data=e;
	 s->next=p->next;//插入L中 
	 p->next=s;
	 return OK;
 }
///////////////////////////////////////////
Status ListDelete_L(LinkList &L,int i,ElemType &e)
{
	//在带头结点的单链表L中,删除第i个元素,并由e返回其值
	 LinkList p,q;
	 p=L;
	 int j=0;
	 //寻找第i个结点,并令p指向其前驱
	 while(p->next&&j<i-1)
	 {
	 	p=p->next;
	 	++j;
	}
	if(!(p->next||j>i-1))
	return ERROR;//删除位置不合理的 
	q=p->next;
	p->next=q->next;//删除并释放结点 
	e=q->data;
	free(q);
	return OK; 
 } 
 //////////////////////////////////////////
 void ShowAddress(LinkList L)
 {
 //展示出每个结点的地址 
 	int i;
 	LinkList p=L->next;
 	if(p!=NULL)
 	{
 		printf("\n头结点的地址为:\t%p\n",L);
 		for(i=1;p!=NULL;i++)
		 {
		 	printf("第%d个结点的值为:\t%d;\t地址为 %p\n",i,p->data,p);
		 	p=p->next;
		  } 
	 }
 }
 /////////////////////////////////////////////////////////////////
void ShowAddress2(LinkList L)
 {
  
 	int i;
 	LinkList p=L->next;
 	if(p!=NULL)
 	{
 		printf("\n头结点的地址为:\t%p\n",L);
 		printf("头结点->");
 		for(i=1;p->next !=NULL;i++)
		 {
		 	printf("%d->",p->data);
		 	p=p->next;
		  } 
		  printf("%d\n",p->data);
	 }
 }
/////////////////////////////////////////////////////// 
 LNode *MaxNode(LNode *L)
 {
 //设计一个算法,通过一趟遍历确定单链表L(至少含两个数据结点)中第一个元素值最大的结点。
 //返回最大值的地址 
 //
 	LNode *p=L->next,*maxp=p;
 	while(p!=NULL)
 	{
 		if(maxp->data<p->data)
 		maxp=p;
 		p=p->next;
 		
	 }
	 return maxp;
 }
 //////////////////////////////////////
 void DelMaxNode(LNode *&L)
{  
//设计一个算法,删除一个单链表L(至少含两个数据结点)中第一个元素值最大的结点。
 
   LNode *p=L->next,*pre=L,*maxp=p,*maxpre=pre;
   while (p!=NULL)
   {    if (maxp->data<p->data)
      {	maxp=p;
	  	maxpre=pre;
      }
      pre=p;	      //pre、p同步后移,保证pre始终为p的前驱结点
      p=p->next;
   }
   maxpre->next=maxp->next;	//删除maxp结点
   free(maxp);			//释放maxp结点
}
//////////////////////////////////////////////////////
void ListReverse(LNode *&L)
{ 

 //设计一个算法,将一个单链表L(至少含两个数据结点)中所有结点逆置,并分析算法的时间复杂度。
   LinkList p=L->next, q;
   L->next=NULL;
   while (p!=NULL)		//遍历所有数据结点
   {	q=p->next;		//q临时保存p结点之后的结点
	p->next=L->next;	//将结点p插入到头结点之后
	L->next=p;
	p = q;
   }
}
//////////////////////////////////////////////
int  Searchk(LinkList list,int k)
{    
//查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0 
//算法的基本设计思想:定义两个指针变量p和q,初始时均指向头结点的下一个结点。p指针沿链表移动;
//当p指针移动到第k个结点时,q指针开始与p指针同步移动;当p指针移动到链表尾结点时,q指针所指元素为倒数第k个结点。
//     以上过程对链表仅进行一遍扫描。
  
    LinkList  p, q;
	int count=0;
	p=q=list->next;
	while (p!=NULL && count<k)	//查找第k个结点*p
	{	 count++;
	p=p->next;
	}
	if (p==NULL)
	{printf("第K个元素的数据为 %d \n",q->data);		//没有时返回0
	return 0;}
	else
	{	while (p!=NULL)	              //p和q同步后移直到p=NULL
	{	q=q->next;
		p=p->next;
	}
	printf("第K个元素的数据为 %d\n",q->data);
	return 1;
	}
}
/////////////////////////////////////////////
void splitList(LinkList head, LinkList &headA, LinkList &headB)
{
//下列算法的功能是:设List={a1,b1,a2,b2,......,an,bn}为一线性表,
//采用带头结点的单链表head存放,设计一个就地算法,将其拆分为两个线性表,
//每个线性表均采用带头结点的单链表存储,使得:A={a1,a2,......,an},B={bn,bn-1,......,b2,b1}。
    LinkList p = head->next, q, r;
    headA = head;
    r = headA;
    headB = (LNode *)malloc(sizeof(LNode));
    headB->next = NULL;
    while (p != NULL) {
        r->next = p;
        r = p;
        p = p->next;
        q = p->next;
        p->next = headB->next;
        headB->next = p;
        p = q;
    }
    r->next = NULL;
} 
////////////////////////////////////////////// 
 void List_deletedulicate(LinkList &L)
 {
 	LinkList pre,cur,temp;
 	pre=L;
 	cur=L->next;
	 while(cur!=NULL)
	 {
	 	if(cur->data ==pre->data )
	 		{temp=cur->next;
	 		free(cur);
	 		cur=temp;
	 		pre->next=temp;}
	 	 else 
		  {
	 	 	pre=pre->next;
	 	 	cur=cur->next;}
	 		
		 
	  } 
 }
/////////////////////////////////////////////////////////
 void List_deletedulicate2(LinkList &L)
 {
 	//可以使用一个计数器,如果有与当前节点重复的节点,
	 //删除掉重复节点之后(因为该链表是有序的,所以重复的就是当前节点的下一个),计数器的值加一。
	 //当前节点重复值删除完之后,判断当前节点是否需要删除就是判断计数器的值是否为0,如果不是0则删除该节点。然后继续遍历
 	
 	
 	
 	
 	LinkList pre,cur,temp,prepre;
 	int flag=0;//记录这个元素是否重复出现过吗
	  
 	prepre=L;
 	pre=L->next;
 	cur=pre->next;
	 while(cur!=NULL)
	 {
	 	if(cur->data ==pre->data )
	 		{flag=1;
			 temp=cur->next;
	 		free(cur);
	 		cur=temp;
	 		pre->next=temp;}
	 	 else 
		  {if(flag==1)
		  	{
		  	prepre->next=cur;
		  	free(pre);
		  	pre=cur;
		  	cur=cur->next;
		  	
		  	}
		  else
		  	{prepre=prepre->next;
	 	 	pre=pre->next;
	 	 	cur=cur->next;}
		  }
	 		
		 
	  } 
 }
void List_Bubble(LinkList &L)  
{  
//冒泡排序 
    LinkList pre;  
    LinkList cur;  
    LinkList next;  
      
    int i, j;  
    i = ListLength(L);  
    printf("length = %d\n", i);  
      
    while(i != 1)//因为当i=1时不需要排序   外层 
    {  
        pre = L;  
                cur = L->next;  
                next = cur->next;  
                j = i;  
        i--;  
        while(j != 1)  //内层 
        {  
            j--;  
            if(cur->data > next->data )  //满足条件则交换 
            {  
                cur->next = next->next;  
                pre->next = next;  
                next->next = cur;  
                  
                pre = next;  
                next = cur->next;  
            }  
            else  //如果不满足则进行下一步 
            {  
                pre = cur;  
                cur = next;  
                next = next->next;  
            }  
        }  
    }     
}

 int main ()
{
	int n=1,a;
	int temp;
	int t,x;
	LinkList P;
	InitList_L(P);
		LinkList help;
		InitList_L(help);
	int location,number;
	printf("---菜单---\n");
	 
	printf("[ 1]:插入元素请输入\n[ 2]:删除元素请输入\n[ 3]:遍历链表请输入\n[ 4]:求链表长度输入\n[ 5]:销毁链表请输入\n");
	printf("[ 6]:求最大值;\n[ 7]:删除一个单链表L(至少含两个数据结点)中第一个元素值最大的结点\n");
	printf("[ 8]:将一个单链表L(至少含两个数据结点)中所有结点逆置(翻转链表)(使用插入法)\n[ 9]:找链表中倒数第k个位置上的结点\n");
	printf("[10]:将一个链表拆分为两个线性表\n[11]:删除有序链表的重复元素算法(删除所有的重复元素,使得最终每个元素只出现一次)\n");
	printf("[12]:删除有序链表的重复元素算法(删除所有的重复元素,只保留原始链表中 没有重复出现 的数字)\n");
	printf("[13]:排序(由小到大的顺序)\n[14]:一次输入n个元素到链表中:\n"); 

	while(n)
	{
		printf("请输入要进行的操作数:");
		scanf("%d",&a); 
		switch(a)
		{
			case 1: 
					printf("输入要插入链表的 位置,元素:\n"); 
					scanf("%d %d",&location,&number); 
					ListInsert_L(P,location,number);
					break;
			case 2:  printf("输入要删除链表元素的 位置,保存返回元素用number:\n"); 
					scanf("%d",&location); 
					ListDelete_L(P, location,number); 
				    break;
			case 3: printf("1:输入地址,2:链式输出选择(1/2)种遍历算法 x:");
					scanf("%d",&x);
					if(x==1) 	ShowAddress(P); 
					else 	ShowAddress2(P);
					break;
			case 4: printf("目前链表长度:");
					printf(" %d \n",ListLength(P));
					break;
			case 5: DestroyList(P);
			 		break;
			case 6: *MaxNode(P);
					printf("最大元素为%d\n",MaxNode(P)->data );
			 		break;
			case 7: DelMaxNode(P); 
					break; 	
			case 8: ListReverse(P);
					break;
			case 9: printf("请输入倒数第K的位置 K:");
					int k;
					scanf("%d",&k);
					Searchk(P,k);
					break;
			case 10:LinkList headA,headB;
					splitList(P, headA, headB);	
					printf("拆分后的两个链表为:\n");
					ShowAddress(headA); 
					ShowAddress(headB); 
					break;	
			case 11:List_deletedulicate(P);
					ShowAddress(P);
					break; 
			case 12:List_deletedulicate2(P);
					ShowAddress2(P);
					break; 
			case 13:List_Bubble(P);
					ShowAddress2(P);
					break;
			case 14:printf("输入n:");
					scanf("%d",&t);
					for(int i=1;i<=t;i++)
					{
					printf("即将进入链表的值为:");
					scanf("%d",&number);
					ListInsert_L(P,i,number);	
					}
					ShowAddress2(P);
					break; 
			
		}
			
	}
	
 } 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值