利用C语言实现顺序表的实例操作_C 语言

本文实例讲述了C语言实现顺序表(线性表)的方法。分享给大家供大家参考,具体如下:

一:顺序表代码实现

#ifndef _SEQ_LIST_H
#define _SEQ_LIST_H

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#define ElemType float  //以float类型测试算法通用性,而不是以惯用的int
#define INIT_SIZE 10  //顺序表默认初始化大小
#define LIST_INCREMENT 5  //顺序表容量增量,容量不够使用malloc申请

#define list_full(list) ((list)->size >= (list)->capacity ? 1 : 0) //顺序表判满
#define list_empty(list) ((list)->size == 0 ? 1 : 0)   //判空

typedef ElemType value_type;   //元素类型
typedef value_type* value_ptr;   //元素指针类型
typedef enum {false, true}bool;   //为C语言增加bool量
typedef enum {POSITION, VALUE}DELETE_MODE; //删除元素模式选择,分别为按位置删除和按值删除

typedef struct sequelize_list{
 ElemType *base;   //顺序表基址
 int size;   //顺序表元素大小
 int capacity;   //顺序表容量
} seq_list, *list_ptr;

void init_list(list_ptr lp)  //初始化
{
 assert(lp != NULL);

 lp->base = (value_ptr)malloc(sizeof(value_type)*INIT_SIZE); //free
 assert(lp->base != NULL);

 memset(lp->base, 0, sizeof(value_type)*INIT_SIZE);

 lp->size = 0;
 lp->capacity = INIT_SIZE;
}

bool insert_elem(list_ptr lp, const int pos, const value_type elem)  //插入元素
{
 assert(lp != NULL && pos >= 1 && pos <= lp->size+1);

 if(list_full(lp)){   //如果表满,追加申请空间
 value_ptr new_base = (value_ptr)realloc(lp->base,
 sizeof(value_type)*(lp->capacity+LIST_INCREMENT));//此处注意realloc用法,用新地址接收是为了防止realloc失败,原地址有效内容被释放
 assert(new_base != NULL); //并且realloc填写的申请空间大小必须是之前的大小+增量的大小,而不是只写增量,否则如果原地址内存不够,在新地址申请增量大小的空间,将之前的内容挪至新空间,内存溢出,将发生段错误

 lp->base = new_base;  //再赋回给原地址
 lp->base[lp->capacity] = elem;
 lp->capacity += LIST_INCREMENT;
 ++lp->size;

 }
 else{    //未满,插入元素
 for(int i=lp->size-1; i>=pos-1; --i){  //将元素后移,腾出位置
 lp->base[i+1] = lp->base[i];
 }

 lp->base[pos-1] = elem;   //插入元素
 ++lp->size;
 //}
 return true;
}

bool remove_elem_pos(list_ptr *lp, const int pos) //按位置删除
{
 assert(pos >= 1 && pos <= (*lp)->size);  

 for(value_ptr ptmp=&(*lp)->base[pos-1]; ptmp<&(*lp)->base[(*lp)->size-1]; ++ptmp)
 *ptmp = *(ptmp+1);

 (*lp)->base[(*lp)->size-1] = 0;
 --(*lp)->size;

 return true;
}

bool remove_elem_val(list_ptr *lp, value_type elem) //按值删除
{
 for(int i=0; i<(*lp)->size; ++i)
 if((*lp)->base[i] == elem){
 for(int j=i; j<(*lp)->size-1; ++j) //所有符合要求的值都被删除
 (*lp)->base[j] = (*lp)->base[j+1];

 (*lp)->base[(*lp)->size-1] = 0;
 --(*lp)->size;
 }
 return true;
}

bool remove_elem(list_ptr lp, const void* clue, DELETE_MODE mode) //外部接口,第三个参数选择按位置或按值删除模式
{
 assert(lp != NULL);

 if(list_empty(lp)){ //表空,不能删
 fprintf(stdout, "already empty, can not remove.\n");
 return false;
 }

 if(mode == POSITION){ //参数为POSITION,按位置删除
 remove_elem_pos(&lp, *(int *)clue);
 }
 else{   //否则按值删除
 remove_elem_val(&lp, *(value_ptr)clue);
 }

 return true;
}

void print_list(const seq_list sl) //打印函数
{
 if(sl.size == 0)
 fprintf(stdout, "nil list.");

 for(int i=0; i<sl.size; ++i)
 printf("%f ", sl.base[i]);
 printf("\n");
}

int compare(const void *vp1, const void* vp2) //比较函数
{
 return *(value_ptr)vp1 - *(value_ptr)vp2;
}

int locate_elem(const seq_list sl, const value_type elem,
  int (*compare)(const void *, const void *)) //定位函数
{
 if(list_empty(&sl)){
 fprintf(stdout, "list empty, con not locate.\n");
 }
 else{
 for(int i=0; i<sl.size; ++i)
 if((*compare)(&sl.base[i], &elem) == 0)  //相等则找到,返回位置
 return i+1;
 }
 return 0;
}

void sort_list(list_ptr lp, int (*compare)(const void *, const void *)) //排序函数
{
 assert(lp != NULL);
 qsort(lp->base, lp->size, sizeof(value_type), compare);   //调用系统快速排序
}

void merge_list(list_ptr lpa, list_ptr lpb, list_ptr combine,
  int (*compare)(const void *, const void *)) //合并两个顺序表
{
 assert(lpa != NULL && lpb != NULL && combine != NULL);

 combine->base = (value_ptr)malloc(sizeof(value_type)
  *(lpa->size+lpb->size)); //此处为新表申请空间,因此新表无需另外调用初始化函数,否则会发生内存泄漏
 assert(combine->base != NULL);

 combine->capacity = combine->size = lpa->size+lpb->size;  

 value_ptr it_pc = combine->base;
 value_ptr it_pa=lpa->base;
 value_ptr it_pb=lpb->base; 

 while(it_pa<lpa->base+lpa->size && it_pb<lpb->base+lpb->size){  //由小到大插入新表
 if(compare(it_pa, it_pb) <= 0)
 *it_pc++ = *it_pa++;
 else
 *it_pc++ = *it_pb++;
 }

 while(it_pa < lpa->base+lpa->size) //从上面while出循环只有两种情况,此处为pa为插完,pb已插完,pa剩余元素直接插入,天然有序
 *it_pc++ = *it_pa++;
 while(it_pb < lpb->base+lpb->size) //同理,若pb剩有元素,直接插入,天然有序
 *it_pc++ = *it_pb++;
}

#endif /*seq_list*/

二:测试代码

为保证通用性,不用int,用float测试。
#include "seq_list.h"

#define ARRAY_SIZE 10

int main()
{
 value_type array[] = {39.1, 32.1, 10.1, 11.1, 22.1, 5.1, 36.1, 28.1, 46.1, 32.1};
 seq_list list; //顺序表1

 init_list(&list);

 for(int i=0; i<ARRAY_SIZE; ++i)
 insert_elem(&list, 1, array[i]);
 printf("list:\n");
 print_list(list);

#if 1
 int clue = 1;   //按顺序删除,删除第一个元素
 //value_type clue = 32.1; //按值删除,删除值为32.1的元素,需修改下面参数为VALUE
 printf("after remove:\n");
 remove_elem(&list, &clue, POSITION);
 print_list(list);
#endif
#if 1
 int found = locate_elem(list, 22.1, compare); //定位22.1元素所在位置
 if(found >= 1)
 fprintf(stdout, "found %f at the position %d\n", list.base[found-1], found);
 else
 fprintf(stdout, "not found.\n");
#endif

 sort_list(&list, compare);
 printf("list after sort:\n");
 print_list(list);

 value_type array2[] = {98.1, 65.1, 4.1, 86.1, 34.1, 21.1, 86.1, 74.1, 93.1, 46.1};
 seq_list list2;

 init_list(&list2);
 for(int i=0; i<ARRAY_SIZE; ++i)
 insert_elem(&list2, 1, array2[i]);
 printf("list2:\n");
 print_list(list2);

 printf("list2 after sort:\n");
 sort_list(&list2, compare);
 print_list(list2);

 seq_list new_list; //无需调用init函数初始化,因为新表在merge_list中会初始化。如果强行调用,那么会出现内存泄漏。

 merge_list(&list, &list2, &new_list, compare);
 printf("new merge_list:\n");
 print_list(new_list);

 free(list.base);
 free(list2.base);
 free(new_list.base); //三个释放,防止内存泄漏

 return 0;
}

三:测试结果

四:总结

以上就是本文的全部内容,希望对大家学习使用C语言能有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索顺序表c语言实现
c语言建立顺序表
c语言顺序表、顺序表c语言实现、c语言顺序表的实现、c语言建立顺序表、c语言顺序表的建立,以便于您获取更多的相关知识。

时间: 2024-10-01 17:01:09

利用C语言实现顺序表的实例操作_C 语言的相关文章

基于C语言实现五子棋游戏完整实例代码_C 语言

本文实例讲述了基于C语言实现五子棋游戏的方法,代码备有比较完整的注释,可以帮助读者更好的加以理解. 五子棋游戏代码如下: /* * 使用键盘的上下左右键移动棋盘,空格键表示下棋,ESC键退出程序 */ #include <stdio.h> #include <stdlib.h> #include <bios.h> #include <graphics.h> #include<malloc.h> /* * 对应键盘键的十六进制数字 */ #defi

C语言选择排序算法及实例代码_C 语言

选择排序是排序算法的一种,这里以从小到大排序为例进行讲解. 基本思想及举例说明 选择排序(从小到大)的基本思想是,首先,选出最小的数,放在第一个位置:然后,选出第二小的数,放在第二个位置:以此类推,直到所有的数从小到大排序. 在实现上,我们通常是先确定第i小的数所在的位置,然后,将其与第i个数进行交换. 下面,以对 3  2  4  1 进行选择排序说明排序过程,使用min_index 记录当前最小的数所在的位置. 第1轮 排序过程 (寻找第1小的数所在的位置) 3  2  4  1(最初, m

C语言实现红黑树的实例代码_C 语言

因为看内核的时候感觉红黑树挺有意思的,所以利用周末的时间来实现一下玩玩.红黑树的操作主要是插入和删除,而删除的时候需要考虑的情况更多一些.具体的操作就不在这里罗嗦了,百度文库里面有一个比较有好的文章,已经说的很明白了. 在看具体的操作的时候有的人可能感觉有些情况是没有考虑到的(如果没有这种感觉的人很有可能根本没有仔细地想).但是那些"遗漏"的情况如果存在的话,操作之前的红黑树将违反那几个规则. 写代码的时候很多次因为少考虑情况而导致错误,细节比较多,刚开始rb_node中没有指向父节点

C语言编写银行打印程序实例参考_C 语言

简介 模拟银行的钱数大写输出例如345叁肆伍 方法/步骤 首先打开VC++ 文件>>>新建 创建一个C++空白文档 先声明头文件 复制代码 代码如下: #include<stdio.h>  声明变量 复制代码 代码如下: char *p[10]={"零","一","二","三","四","五","六","七",&quo

C语言实现顺序表基本操作汇总_C 语言

本文汇总了C语言下实现及操作顺序表的方法,对于学习数据结构的朋友来说是一个不错的参考程序.完整代码如下: #include<stdio.h> #include<stdlib.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define LIST_INIT_SIZE 100 #define LISTINCREMENT 10 typedef int status ;

C++实现顺序表的常用操作(插入删出查找输出)_C 语言

实现顺序表的插入,删除,查找,输出操作在C语言中经常用到.下面小编给大家整理实现代码,一起看下吧 代码如下所示: #include<iostream> using namespace std; #define MAXSIZE 15 typedef int DataType; typedef struct { DataType data[MAXSIZE]; //通常用一位数组来描述顺序表的数据存储 int SeqLength; /*线性表长度*/ } SeqList; SeqList *Init

数据结构 语言-关于顺序表操作的问题

问题描述 关于顺序表操作的问题 输入一组整形元素序列,建立顺序表.要求:(1)实现顺序表的遍历.查找.插入.删除:(2)实现将顺序表中所有奇数排在偶数之前,表的前面为奇数,后面为偶数: 解决方案 java实现: 这个顺序表可以封装两个TreeSet,一个放奇数,一个放偶数.遍历: 返回两个set的集合,先返回骑术的,再返回偶数的.查找: 先判断奇偶,然后直接到set里查,so easy.插入: 先判断奇偶,然后add到对应的set.删除: 同理. 解决方案二: http://blog.csdn.

c语言实现顺序表的基本操作_C 语言

数据结构顺序表操作 复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <malloc.h>#define LIST_INIT_SIZE 100#define LISINCREMENT 10#define ElemType int#define Status inttypedef struct Sq{ ElemType *elem; int length; int listsize;}SqList;Statu

C++虚函数表实例分析_C 语言

多态是C++面向对象程序设计的一个重要特性.以前看到虚函数觉得很神奇,为什么就能实现多态了呢.最初的时候曾设想,要实现运行时多态,应该让对象的某个部分始终指向一个固定的地址,子类继承的时候,就修改这个地址的内容.这样,父类和子类都是到同一个固定地址去读取内容,在运行时就能表现不同行为. 在看了<深度探索c++对象模型>之后,发现思路是类似的.在对象中,有一个指针指向一张虚函数表,里面按照次序存放了每一个虚函数,当子类继承的时候,即到虚函数表的指定位置去修改函数地址.当我们通过父类指针来操作一个